#!/usr/bin/perl
## BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]

#

#============================================================================
# initialization
use strict;
use Term::ANSIColor;
use Term::ANSIColor qw(:constants);
use File::Basename;
use Math::BigInt;
use Cwd;

#Setup some defaults
my $exit_code=0;

my $Force_Install = 0;# force option used to force install on unsupported distro
my $GPU_Install = 0;
my $HFI2_INSTALL = 0; # indicate whether we shall install HFI2
# When --user-space is selected we are targeting a user space container for
# installation and will skip kernel modules and firmware
my $user_space_only = 0; # can be set to 1 by --user-space argument

# some options specific to OFA builds
my $OFED_force_rebuild=0;

my $CUR_OS_VER = `uname -r`;
chomp $CUR_OS_VER;

# related to HFI2_INSTALL. The following code is introduced to help us check b-s-m kernel for HFI2.
# After we merge HFI2 into ifs-kernel-updates, we shall remove the following.
my $CUR_OS_VER_SHORT = '';
if ($CUR_OS_VER =~ /([0-9]+\.[0-9]+)/ ) {
	$CUR_OS_VER_SHORT=$1;
} else {
	die "\n\nKernel version \"${CUR_OS_VER}\" doesn't have an extractable major/minor version!\n\n";
}

my $RPMS_SUBDIR = "RPMS";
my $SRPMS_SUBDIR = "SRPMS";

# firmware and data files
my $OLD_BASE_DIR = "/etc/sysconfig/opa";
my $BASE_DIR = "/etc/opa";
# iba editable config scripts
my $OPA_CONFIG_DIR = "/etc/opa";

my $UVP_CONF_FILE = "$BASE_DIR/uvp.conf";
my $UVP_CONF_FILE_SOURCE = "uvp.conf";
my $DAT_CONF_FILE_SOURCE = "dat.conf";
my $NETWORK_CONF_DIR = "/etc/sysconfig/network-scripts";
my $BIN_DIR = "/usr/sbin";

#This string is compared in verify_os_rev for correct revision of
#kernel release.
my $CUR_DISTRO_VENDOR = "";
my $CUR_VENDOR_VER = "";	# full version (such as ES5.1)
my $CUR_VENDOR_MAJOR_VER = "";    # just major number part (such as ES5)
my $ARCH = `uname -m | sed -e s/ppc/PPC/ -e s/powerpc/PPC/ -e s/i.86/IA32/ -e s/ia64/IA64/ -e s/x86_64/X86_64/`;
chomp $ARCH;
my $DRIVER_SUFFIX=".o";
if (substr($CUR_OS_VER,0,3) eq "2.6" || substr($CUR_OS_VER,0,2) eq "3.")
{
	$DRIVER_SUFFIX=".ko";
}
my $DBG_FREE="release";


# Command paths
my $RPM = "/bin/rpm";

# a few key commands to verify exist
my @verify_cmds = ( "uname", "mv", "cp", "rm", "ln", "cmp", "yes", "echo", "sed", "chmod", "chown", "chgrp", "mkdir", "rmdir", "grep", "diff", "awk", "find", "xargs", "sort");

# opa-scripts expects the following env vars to be 0 or 1. We set them to the default value here
setup_env("OPA_INSTALL_CALLER", 0);
default_opascripts_env_vars();

sub Abort(@);
sub NormalPrint(@);
sub LogPrint(@);
sub HitKeyCont();
# ============================================================================
# General utility functions

# verify the given command can be found in the PATH
sub check_cmd_exists($)
{
	my $cmd=shift();
	return (0 == system("which $cmd >/dev/null 2>/dev/null"));
}

sub check_root_user()
{
	my $user;
	$user=`/usr/bin/id -u`;
	if ($user != 0)
	{
		die "\n\nYou must be \"root\" to run this install program\n\n";
	}

	@verify_cmds = (@verify_cmds, rpm_get_cmds_for_verification());
	# verify basic commands are in path
	foreach my $cmd ( @verify_cmds ) {
		if (! check_cmd_exists($cmd)) {
			die "\n\n$cmd not found in PATH.\nIt is required to login as root or su - root.\nMake sure the path includes /sbin and /usr/sbin\n\n";
		}
	}
}

sub my_tolower($)
{
	my($str) = shift();

	$str =~ tr/[A-Z]/[a-z]/;
	return "$str";
}

# ============================================================================
# Version and branding

# version string is filled in by prep, special marker format for it to use
my $VERSION = "THIS_IS_THE_ICS_VERSION_NUMBER:@(#)10.11.1.2.2% 00B000";
$VERSION =~ s/THIS_IS_THE_ICS_VERSION_NUMBER:@\(#\)//;
$VERSION =~ s/%.*//;
my $INT_VERSION = "THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@(#)10_11_1_2_2% 00B000";
$INT_VERSION =~ s/THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@\(#\)//;
$INT_VERSION =~ s/%.*//;
my $BRAND = "THIS_IS_THE_ICS_BRAND:Cornelis%                 ";
# backslash before : is so patch_brand doesn't replace string
$BRAND =~ s/THIS_IS_THE_ICS_BRAND\://;
$BRAND =~ s/%.*//;

# convert _ and - in version to dots
sub dot_version($)
{
	my $version = shift();

	$version =~ tr/_-/./;
	return $version;
}

# ============================================================================
# installation paths

# where to install libraries
my $LIB_DIR = "/lib";
my $UVP_LIB_DIR = "/lib";
my $USRLOCALLIB_DIR = "/usr/local/lib";
my $OPTIBALIB_DIR = "/usr/lib/opa/lib";
my $USRLIB_DIR = "/usr/lib";
# if different from $LIB_DIR, where to remove libraries from past release
my $OLD_LIB_DIR = "/lib";
my $OLD_USRLOCALLIB_DIR = "/usr/local/lib";
my $OLD_UVP_LIB_DIR = "/lib";

sub set_libdir()
{
	if ( -d "/lib64" )
	{
		$LIB_DIR = "/lib64";
		$UVP_LIB_DIR = "/lib64";
		$UVP_CONF_FILE_SOURCE = "uvp.conf.64";
		$DAT_CONF_FILE_SOURCE = "dat.conf.64";
		$USRLOCALLIB_DIR = "/usr/local/lib64";
		$OPTIBALIB_DIR = "/usr/lib/opa/lib64";
		$USRLIB_DIR = "/usr/lib64";
	}
}

# determine the os vendor release level based on build system
# this script is stolen from funcs-ext.sh and should
# be maintained in parallel
sub os_vendor_version($)
{
	my $vendor = shift();

	my $rval = "";
	my $mn = "";
	if ( -e "/etc/os-release" ) {
		if ($vendor eq "ubuntu") {
			$rval=`cat /etc/os-release | grep VERSION_ID | cut -d'=' -f2 | tr -d [\\"\\.]`;
		} else {
			$rval=`cat /etc/os-release | grep VERSION_ID | cut -d'=' -f2 | tr -d [\\"\\.0]`;
		}
		chop($rval);
		$rval="ES".$rval;
		if ( -e "/etc/redhat-release" ) {
			if (!system("grep -qi centos /etc/redhat-release")) {
				$rval = `cat /etc/redhat-release | cut -d' ' -f4`;
				$rval =~ m/(\d+).(\d+)/;
				if ($2 eq "0") {
					$rval="ES".$1;
				} else {
					$rval="ES".$1.$2;
				}
			} elsif (!system("grep -qi rocky /etc/redhat-release")) {
				$rval = `cat /etc/redhat-release | cut -d' ' -f4`;
				$rval =~ m/(\d+).(\d+)/;
				if ($2 eq "0") {
					$rval="ES".$1;
				} else {
					$rval="ES".$1.$2;
				}
			}	
		}
	} elsif ($vendor eq "apple") {
		$rval=`sw_vers -productVersion|cut -f1-2 -d.`;
		chop($rval);
	} elsif ($vendor eq "rocks") {
		$rval=`cat /etc/rocks-release | cut -d' ' -f3`;
		chop($rval);
	} elsif ($vendor eq "scyld") {
		$rval=`cat /etc/scyld-release | cut -d' ' -f4`;
		chop($rval);
	} elsif ($vendor eq "mandrake") {
		$rval=`cat /etc/mandrake-release | cut -d' ' -f4`;
		chop($rval);
	} elsif ($vendor eq "fedora") {
		$rval=`cat /etc/fedora-release | cut -d' ' -f4`;
		chop($rval);
	} elsif ($vendor eq "redhat") {
		if (!system("grep -qi advanced /etc/redhat-release")) {
			$rval=`cat /etc/redhat-release | cut -d' ' -f7`;
			chop($rval);
		} elsif (!system("grep -qi centos /etc/redhat-release")) {
			# Find a number of the form "#.#" and output the portion
			# to the left of the decimal point.
			$rval = `cat /etc/redhat-release`;
			$rval =~ m/(\d+).(\d+)/;
			$rval="ES".$1.$2;
		} elsif (!system("grep -qi Scientific /etc/redhat-release")) {
			# Find a number of the form "#.#" and output the portion
			# to the left of the decimal point.
			$rval = `cat /etc/redhat-release`;
			$rval =~ m/(\d+).(\d+)/;
			$rval="ES".$1;
		} elsif (!system("grep -qi rocky /etc/redhat-release")) {
			# Find a number of the form "#.#" and output the portion
			# to the left of the decimal point.
			$rval = `cat /etc/redhat-release`;
			$rval =~ m/(\d+).(\d+)/;
			$rval="ES".$1.$2;
		} elsif (!system("grep -qi enterprise /etc/redhat-release")) {
			# Red Hat Enterprise Linux Server release $a.$b (name)
			#PR 110926
			$rval=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d'.' -f1`;
			$mn=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d'.' -f2`;
			chop($rval);
			if ( (($rval >= 7) && ($mn > 0)) ||
				(($rval == 6) && ($mn >= 7)) ) {
				chomp($mn);
				$rval=join "","ES","$rval","$mn";
			} else {
				$rval="ES".$rval;
			}
		} else {
			$rval=`cat /etc/redhat-release | cut -d' ' -f5`;
			chop($rval);
		}
	} elsif ($vendor eq "UnitedLinux") {
		$rval=`grep United /etc/UnitedLinux-release | cut -d' ' -f2`;
		chop($rval);
	} elsif ($vendor eq "SuSE") {
		if (!system("grep -qi enterprise /etc/SuSE-release")) {
			$rval=`grep -i enterprise /etc/SuSE-release | cut -d' ' -f5`;
			chop($rval);
			$rval="ES".$rval;
		} else {
			$rval=`grep SuSE /etc/SuSE-release | cut -d' ' -f3`;
			chop($rval);
		}
	} elsif ($vendor eq "turbolinux") {
		$rval=`cat /etc/turbolinux-release | cut -d' ' -f3`;
		chop($rval);
	}
	return $rval;
}

# Get OS distribution, vendor and vendor version
# set CUR_DISTRO_VENDOR, CUR_VENDOR_VER, CUR_VENDOR_MAJOR_VER
sub determine_os_version()
{
	# we use the current system to select the distribution
	# TBD we expect client image for diskless client install to have these files
	my $os_release_file = "/etc/os-release";
	if ( -e "/etc/redhat-release" && !(-l "/etc/redhat-release") ) {
		$CUR_DISTRO_VENDOR = "redhat";
	} elsif ( -s "/etc/centos-release" ) {
		$CUR_DISTRO_VENDOR = "redhat";
	} elsif ( -s "/etc/rocky-release" ) {
		$CUR_DISTRO_VENDOR = "redhat";
	} elsif ( -s "/etc/UnitedLinux-release" ) {
		$CUR_DISTRO_VENDOR = "UnitedLinux";
		$NETWORK_CONF_DIR = "/etc/sysconfig/network";
	} elsif ( -s "/etc/SuSE-release" ) {
		$CUR_DISTRO_VENDOR = "SuSE";
		$NETWORK_CONF_DIR = "/etc/sysconfig/network";
	} elsif ( -e "/usr/bin/lsb_release" ) {
		$CUR_DISTRO_VENDOR = `/usr/bin/lsb_release -is`;
		chop($CUR_DISTRO_VENDOR);
		$CUR_DISTRO_VENDOR = lc($CUR_DISTRO_VENDOR);
		if ($CUR_DISTRO_VENDOR eq "suse") {
			$CUR_DISTRO_VENDOR = "SuSE";
		}
	} elsif ( -e $os_release_file) {
		my %distroVendor = (
			"rhel" => "redhat",
			"centos" => "redhat",
			"rocky" => "redhat",
			"sles" => "SuSE",
			"sle_hpc" => "SuSE"
		);
		my %network_conf_dir  = (
			"rhel" => $NETWORK_CONF_DIR,
			"centos" => $NETWORK_CONF_DIR,
			"rocky" => $NETWORK_CONF_DIR,
			"sles" => "/etc/sysconfig/network",
			"sle_hpc" => "/etc/sysconfig/network"
		);
		my $os_id = `cat $os_release_file | grep '^ID=' | cut -d'=' -f2 | tr -d [\\"\\.0] | tr -d ["\n"]`;
		$CUR_DISTRO_VENDOR = $distroVendor{$os_id};
		$NETWORK_CONF_DIR = $network_conf_dir{$os_id};
	} else {
		# autodetermine the distribution
		open DISTRO_VENDOR, "ls /etc/*-release|grep -v lsb\|^os 2>/dev/null |"
			|| die "Unable to open pipe\n";
		$CUR_DISTRO_VENDOR="";
		while (<DISTRO_VENDOR>) {
			chop;
			if (!(-l $_)) {
				my $CDV  = fileparse($_, '-release');
				if ( "$CDV" ne "rocks" ) {
					$CUR_DISTRO_VENDOR = $CDV;
				}
			}
		}
		close DISTRO_VENDOR;
		if ( $CUR_DISTRO_VENDOR eq "" )
		{
			NormalPrint "Unable to determine current Linux distribution.\n";
			Abort "Please contact your support representative...\n";
		} elsif ($CUR_DISTRO_VENDOR eq "SuSE") {
			$NETWORK_CONF_DIR = "/etc/sysconfig/network";
		} elsif ($CUR_DISTRO_VENDOR eq "centos") {
			$CUR_DISTRO_VENDOR = "redhat";
		} elsif ($CUR_DISTRO_VENDOR eq "rocky") {
			$CUR_DISTRO_VENDOR = "redhat";
		}
	}
	$CUR_VENDOR_VER = os_vendor_version($CUR_DISTRO_VENDOR);
	$CUR_VENDOR_MAJOR_VER = $CUR_VENDOR_VER;
	$CUR_VENDOR_MAJOR_VER =~ s/\..*//;	# remove any . version suffix
}

# verify distrib of this system matches files indicating supported
#  arch, distro, distro_version
sub verify_distrib_files
{
	my $supported_arch=`cat ./arch 2>/dev/null`;
	chomp($supported_arch);
	my $supported_distro_vendor=`cat ./distro 2>/dev/null`;
	chomp($supported_distro_vendor);
	my $supported_distro_vendor_ver=`cat ./distro_version 2>/dev/null`;
	chomp($supported_distro_vendor_ver);

	if ( "$supported_arch" eq "" || $supported_distro_vendor eq ""
		|| $supported_distro_vendor_ver eq "") {
		NormalPrint "Unable to proceed: installation image corrupted or install not run as ./INSTALL\n";
		NormalPrint "INSTALL must be run from within untar'ed install image directory\n";
		Abort "Please contact your support representative...\n";
	}

	# Make ES79 look like ES78 for installation
	if ( "$CUR_VENDOR_VER" eq "ES79" ) {
		$CUR_VENDOR_VER="ES78";
	}

	my $archname;
	my $supported_archname;
	if ( "$supported_arch" ne "$ARCH"
		|| "$supported_distro_vendor" ne "$CUR_DISTRO_VENDOR"
		|| ("$supported_distro_vendor_ver" ne "$CUR_VENDOR_VER"
			&& "$supported_distro_vendor_ver" ne "$CUR_VENDOR_MAJOR_VER"))
	{
		#LogPrint "Unable to proceed, $CUR_DISTRO_VENDOR $CUR_VENDOR_VER not supported by $INT_VERSION media\n";

		$archname=$ARCH;
		if ( $ARCH eq "IA32") {
			$archname="the Pentium Family";
		} 
		if ( $ARCH eq "IA64" ) {
			$archname="the Itanium family";
		} 
		if ( $ARCH eq "X86_64" ) {
			$archname="the EM64T or Opteron";
		} 
		if ( $ARCH eq "PPC64" ) {
			$archname="the PowerPC 64 bit";
		} 
		if ( $ARCH eq "PPC" ) {
			$archname="the PowerPC";
		} 
		
		NormalPrint "$CUR_DISTRO_VENDOR $CUR_VENDOR_VER for $archname is not supported by this installation\n";
		NormalPrint "This installation supports the following Linux Distributions:\n";
		$supported_archname=$ARCH;
		if ( $supported_arch eq "IA32") {
			$supported_archname="the Pentium Family";
		} 
		if ( $supported_arch eq "IA64" ) {
			$supported_archname="the Itanium family";
		} 
		if ( $supported_arch eq "X86_64" ) {
			$supported_archname="the EM64T or Opteron";
		} 
		if ( $supported_arch eq "PPC64" ) {
			$supported_archname="the PowerPC 64 bit";
		} 
		if ( $supported_arch eq "PPC" ) {
			$supported_archname="the PowerPC";
		} 
		NormalPrint "For $supported_archname: $supported_distro_vendor.$supported_distro_vendor_ver\n";
		if ( $Force_Install ) {
			NormalPrint "Installation Forced, will proceed with risk of undefined results\n";
			HitKeyCont;
		} else {
			Abort "Please contact your support representative...\n";
		}
	}
}

# set the env vars to their default value, when the first we install opa-scripts, we will have proper configs
sub default_opascripts_env_vars()
{
	setup_env("OPA_UDEV_RULES", 1);
	setup_env("OPA_LIMITS_CONF", 1);
	setup_env("OPA_ARPTABLE_TUNING", 1);
	setup_env("OPA_SRP_LOAD", 0);
	setup_env("OPA_SRPT_LOAD", 0);
	setup_env("OPA_IRQBALANCE", 1);
}

# this will be replaced in component specific INSTALL with any special
# overrides of things in main*pl
sub overrides()
{
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ==========================================================================
# Installation logging

my $LogLevel = 0;	# 0 = normal/quiet, 1=verbose, 2=very verbose
my $LogFile = "/dev/null";	# set when open_log

sub open_log(;$)
{
	my($logfile) = shift();
	if ( "$logfile" eq "" ) {
		$logfile="/var/log/opa.log";
	}
	$LogFile = $logfile;
	open(LOG_FD, ">>$logfile");
	print LOG_FD "-------------------------------------------------------------------------------\n";
	print LOG_FD my_basename($0) . " $INT_VERSION Run " . `/bin/date`;
	print LOG_FD "$0 @ARGV\n";
	print LOG_FD "Current Dir: " .  getcwd() . "\n";
}

sub close_log()
{
	close LOG_FD;
}

# output to log and screen and die
sub Abort(@)
{
	print(LOG_FD @_);
	die(@_);
}

# output to log and screen
sub NormalPrint(@)
{
	print(@_);
	print(LOG_FD @_);
}

# output to log only
sub LogPrint(@)
{
	print(LOG_FD @_);
}

sub VerbosePrintEnabled()
{
	return ($LogLevel >= 1);
}

sub VerbosePrint(@)
{
	if (VerbosePrintEnabled() ) {
		print(LOG_FD @_);
	}
}
sub DebugPrintEnabled()
{
	return ($LogLevel >= 2);
}

sub DebugPrint(@)
{
	if (DebugPrintEnabled() ) {
		print(LOG_FD @_);
	}
}

# ============================================================================
# Basic input and prompting routines
my $KEY_ESC=27;
my $KEY_CNTL_C=3;
my $KEY_ENTER=13;

my $Default_Prompt=0;	 # use default values at prompts, non-interactive

sub getch()
{
	my $c;
	system("stty -echo raw");
	$c=getc(STDIN);
	system("stty echo -raw");
	return $c;
}

sub HitKeyCont()
{
	if ( $Default_Prompt )
	{
		return;
	}

	print "Hit any key to continue...";
	getch();
	return;
}

sub remove_whitespace($)
{
	my $string=shift();
	chomp($string);
	$string =~ s/^[[:space:]]*//;	# remove leading
	$string =~ s/[[:space:]]*$//;	# remove trailing
	return $string;
}

# return numeric value: minimum <= value <= maximum
sub GetNumericValue($$$$)
{
	my($retval) = 0;

	my($Question) = $_[0];
	my($default) = $_[1];
	my($minvalue) = $_[2];
	my($maxvalue) = $_[3];

        if ( $Default_Prompt ) {
		NormalPrint "$Question -> $default\n";
		if (($default ge $minvalue) && ($default le $maxvalue)) {
			return $default;
		}
		# for invalid default, fall through and prompt
	}

	while (1)
	{
		NormalPrint "$Question [$default]: ";
		chomp($retval = <STDIN>);
		$retval=remove_whitespace($retval);

		if (length($retval) == 0) {
			$retval=$default;
		}
		if (($retval >= $minvalue) && ($retval <= $maxvalue)) {
			LogPrint "$Question -> $retval\n";
			return $retval;
		}
		else {
			NormalPrint "Value Out-of-Range\n";
                }
	}        
}

#return 0 for no, 1 for yes
sub GetYesNo($$)
{
	my($Question) = shift();
	my($default) = shift();

	my($retval) = 1;
	my($answer) = 0;

	if ( $Default_Prompt ) {
		NormalPrint "$Question ->$default\n";
		if ( "$default" eq "y") {
			return 1;
		} elsif ("$default" eq "n") {
			return 0;
		}
		# for invalid default, fall through and prompt
	}

	while ($answer == 0)
	{
		print "$Question [$default]: ";
		chomp($_ = <STDIN>);
		$_=remove_whitespace($_);
		if ("$_" eq "") {
			$_=$default;
		}
		if (/^[Nn]/) 
		{
			LogPrint "$Question -> n\n";
			$retval = 0;
			$answer = 1;
		} elsif (/^[Yy]/ ) {
			LogPrint "$Question -> y\n";
			$retval = 1;
			$answer = 1;
		}
	}        
	return $retval;
}

# we keep answers in text format.  This way we can later enhance the command
# line argument list to allow answers to more complex questions
my %AnswerMemory = ();	# keep track of past answers to yes/no questions

my @AnswerHelp = ();	# help test for each keyword

sub AddAnswerHelp($$)
{
	my($Keyword) = shift();
	my($help) = shift();

	# check for duplicates, skip if already in list
	foreach my $ans (@AnswerHelp)
	{
		if ($ans =~ m/^$Keyword -/)
		{
			return;
		}
	}
	@AnswerHelp = (@AnswerHelp, "$Keyword - $help");
}

sub showAnswerHelp()
{
	if (scalar(@AnswerHelp) != 0) {
	 	printf STDERR "       --answer keyword=value - provide an answer to a question which might\n";
	 	printf STDERR "            occur during the operation.  answers to questions which are not\n";
	 	printf STDERR "            asked are ignored.  Invalid answers will result in prompting\n";
	 	printf STDERR "            for interactive installs or use of the default for non-interactive.\n";
		printf STDERR "            Possible Questions:\n";
		foreach my $help (@AnswerHelp) {
			printf STDERR "              $help\n";
		}
	} else {
	 	printf STDERR "       --answer keyword=value - presently ignored\n";
	}
}

# similar to GetYesNo, except if the question has already been answered
# (or defaulted on the command line), the question is not asked, instead the
# previous answer is provided
sub GetYesNoWithMemory($$$$)
{
	my($Keyword) = shift();	# unique keyword to identify question
	my($remember) = shift(); # remember answer for use next time
	my($Question) = shift(); # the question shown to user
	my($default) = shift();	# the default to use if not already remembered
	my($retval);

	if ( exists $AnswerMemory{"$Keyword"})
	{
		$_ = $AnswerMemory{"$Keyword"};
		if (/^[Nn]/) 
		{
			NormalPrint "$Keyword: $Question -> n\n";
			$retval = 0;
		} elsif (/^[Yy]/ ) {
			NormalPrint "$Keyword: $Question -> y\n";
			$retval = 1;
		} else {
			# invalid answer, now what?  prompt?
			NormalPrint "$Keyword: $Question -> Invalid answer: $_\n";
			delete $AnswerMemory{"$Keyword"};
		}
	}
	if ( ! exists $AnswerMemory{"$Keyword"})
	{
		$retval = GetYesNo($Question, $default);
		if ($remember) {
			my($ans);
			if ( $retval ) {
				$ans = "y";
			} else {
				$ans = "n";
			}
			$AnswerMemory{"$Keyword"} = $ans;
		}
	}
	return $retval;
}

sub set_answer($$)
{
	my($Keyword) = shift();	# unique keyword to identify question
	my($answer) = shift(); # answer to question

	$AnswerMemory{"$Keyword"} = $answer;
}

sub clear_answer($)
{
	my($Keyword) = shift();

	delete $AnswerMemory{"$Keyword"};
}

sub clear_all_answers($)
{
	my $Keyword;

	foreach $Keyword (keys(%AnswerMemory))
	{
		delete $AnswerMemory{"$Keyword"};
	}
}


#return choice
sub GetChoice($$@)
{
	my($Question) = shift();
	my($default) = shift();
	my(@choices) = @_;	# single character choices

	my $c;

	if ( $Default_Prompt ) {
		NormalPrint "$Question -> $default\n";
		foreach $c ( @choices )
		{
			if (my_tolower("$default") eq my_tolower("$c")) {
				return $c;
			}
		}
		# for invalid default, fall through and prompt
	}

	while (1)
	{
		print "$Question [$default]: ";
		chomp($_ = <STDIN>);
		$_=remove_whitespace($_);
		if ("$_" eq "") {
			$_=$default;
		}
		$_ = my_tolower($_);
		foreach $c ( @choices )
		{
			if ("$_" eq my_tolower("$c")) {
				LogPrint "$Question -> $c\n";
				return $c;
			}
		}
	}        
	# NOTREACHED
}

sub print_separator()
{
	print "-------------------------------------------------------------------------------\n";
}

# based on files on install media update DBG_FREE
# if both release and debug are available on media, prompt user
# This routine checks both the location for IbAccess and Open IB FF installs
sub select_debug_release($)
{
	my($srcdir) = shift();
	my $inp;

	# check current directory to determine if Debug available
	if ( (! -d "$srcdir/bin/$ARCH/$CUR_OS_VER/debug") 
	    and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_VER/lib/debug")
	    and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_MAJOR_VER/lib/debug") )
	{
		# no choice, only release available
		$DBG_FREE="release";
	}
	elsif ( (! -d "$srcdir/bin/$ARCH/$CUR_OS_VER/release")
			and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_VER/lib/release")
			and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_MAJOR_VER/lib/release") )
	{
		# no choice, only debug available
		$DBG_FREE="debug";
	} elsif ( $Default_Prompt ) {
		$DBG_FREE="release";
		printf ("Installing $DBG_FREE Software\n");
	} else {
		printf ("Both Release and Debug versions are available\n\n");
		printf ("Please select which version should be used for install or upgrade operations:\n\n");
		printf ("1) Release Software\n");
		printf ("2) Debug Software\n");

		$inp = getch();

		if ($inp == 1)
		{
			$DBG_FREE="release";
		}
		elsif ($inp == 2)
		{
			$DBG_FREE="debug";
		}
		else 
		{
			printf ("Invalid Choice...\n");
			HitKeyCont;
			return;
		}
	}
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ===========================================================================
# Basic file/directory install/remove

my $OWNER = "root";
my $GROUP = "root";

# remove any directory prefixes from path
sub my_basename($)
{
	my($path) = shift();

	$path =~ s/.*\/(.*)$/$1/;
	return $path;
}

# check for a file using a glob pattern
# return 1st filename to match pattern
# return "" if no match
sub file_glob($)
{
	my $globpat = shift();	# glob pattern to expand

	my $file;
	# there is a little perl trick here, glob returns a list of matching
	# files.  If we simply assigned glob to a scalar it would retain
	# the rest of the list and return subsequent entries on future glob calls
	# then it would return "" after the last matched name.
	# Hence even if glob matched only 1 name, it would return a 2nd ""
	# value to a future caller.  real subtle problem to figure out.
	
	# the list assignment below allows glob to return a list
	# and all extra list entries are discarded.  Hence this returns the
	# first filename which matches or "" if none are matched
	( $file) = glob("$globpat");

	return "$file";
}

sub make_dir($$$$)
{
	my($dir) = shift();
	my($owner) = shift();
	my($group) = shift();
	my($mode) = shift();

	system "mkdir -p -m $mode $dir";
	system "chown $owner $dir";
	system "chgrp $group $dir";
}

sub check_dir($)
{
	my($dir) = shift();
	if (! -d "$dir" ) 
	{
		#Creating directory 

		make_dir("$dir", "$OWNER", "$GROUP", "ugo=rx,u=rwx");
	}
}

sub copy_file($$$$$)
{
	my($src) = shift();
	my($dest) = shift();
	my($owner) = shift();
	my($group) = shift();
	my($mode) = shift();
	# only copy file if source exists, this keep all those cp errors for litering
	# install for development.

	if ( -e $src)
	{               
		system "cp -rf $src $dest";
		system "chown $owner $dest";
		system "chgrp $group $dest";
		system "chmod $mode $dest";
	}
}

sub symlink_usrlocal($$)
{
	my($src) = shift();
	my($dest) = shift();
}

sub copy_all_files($$$$$;$)
{
	my($src_dir)=shift();
	my($dest_dir)=shift();
	my($owner) = shift();
	my($group) = shift();
	my($mode) = shift();
	my($symlink_dir) = shift();	# optional argument
	my(@files);
	my $f;
	my $d;

	if (!-d "$src_dir" )
	{
	 	return;	
	}
	if (!-d "$dest_dir")
	{
		return;
	}
	@files = glob("$src_dir/*");
	foreach $f (@files)
	{
		$d= my_basename($f);
		if (!-d $f)
		{
			copy_file($f, "$dest_dir/$d", $owner, $group, $mode);
			if ( "$symlink_dir" ne "") {
				symlink_usrlocal("$dest_dir/$d", "$symlink_dir/$d");
			}
		} else {
			check_dir("$dest_dir/$d");
				copy_all_files($f, "$dest_dir/$d", $owner, $group, $mode,"");
			}
		}
	}

sub remove_file($)
{
	my($file) = shift();
	system "rm -f $file";
}

sub copy_data_file($$)
{
	copy_file("$_[0]", "$_[1]", "$OWNER", "$GROUP", "ugo=r,u=rw");
}

sub copy_systool_file($$)
{
	# Administrator execution only
	copy_file("$_[0]", "$_[1]", "$OWNER", "$GROUP", "ug=rx,u=rwx");
}

# (as listed in .files and .dirs)
# $0 = dirname relative to 
sub remove_installed_files($)
{
	my $dirname = shift();

	# remove files we installed or user compiled, however do not remove
	# any logs or other files the user may have created
	if ( -d "/$dirname" ) {
		system "cd /$dirname; for dir in `cat .dirs 2>/dev/null`; do ( cd \$dir; make clobber ) >/dev/null 2>&1; done";
		system "cd /$dirname; cat .files 2>/dev/null|xargs rm -f 2>/dev/null";
		system "cd /$dirname; cat .files 2>/dev/null|sort -r|xargs rmdir 2>/dev/null";
		system "rm -f /$dirname/.files 2>/dev/null";
		system "rm -f /$dirname/.dirs 2>/dev/null";
		system "rmdir /$dirname/ 2>/dev/null";
	}
}

# ===========================================================================
# Shared Libaries
my $RunLdconfig=0;

sub check_ldconfig()
{
	if ($RunLdconfig == 1 )
	{
		print_separator;
		print "Updating dynamic linker cache...\n";
		# this is how /etc/rc.sysinit runs ldconfig
		#LogPrint "Updating dynamic linker cache: /sbin/ldconfig -n /lib\n";
		#system "/sbin/ldconfig -n /lib > /dev/null 2>&1";
		LogPrint "Updating dynamic linker cache: /sbin/ldconfig\n";
		system "/sbin/ldconfig > /dev/null 2>&1";
		$RunLdconfig=0;
		return 1;
	}
	return 0;
}

# ===========================================================================
# Will Reboot be required
my $NeedReboot=0;
sub need_reboot()
{
	$NeedReboot=1;
}

sub check_need_reboot()
{
	if ($NeedReboot == 1 )
	{
		print_separator;
		print BOLD, RED, "A System Reboot is recommended to activate the software changes\n", RESET;
		LogPrint "A System Reboot is recommended to activate the software changes\n";
		return 1;
	}
	return 0;
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

#

use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ========================================================================
# Basic configuration files

my $CONFIG_DIR = "/etc"; # general driver config
my $OFED_CONFIG_DIR = "/etc/infiniband"; # general driver config
my $OFED_CONFIG = "$OFED_CONFIG_DIR/openib.conf";
my $OPA_CONFIG_DIR = "/etc/rdma"; 
my $OPA_CONFIG = "$OPA_CONFIG_DIR/rdma.conf";
my %KeepConfig = (); # keep track of past questions to config questions
my $Default_RpmConfigKeepOld=0; # -O option used to select current rpm config file
my $Default_RpmConfigUseNew=0; # -N option used to select new rpm config file

my $TMP_CONF="/tmp/conf.$$";	# scratch file

sub check_config_dirs()
{
	check_dir("$BASE_DIR");
	check_dir("$OPA_CONFIG_DIR");
}

sub check_keep_config($$$)
{
	my($configFile) = shift();
	my($configDesc) = shift();
	my($default) = shift();

	my($prompt) = "";
	my $keep;

	if ("$configDesc" eq "")
	{
		$prompt="$configFile";
	} else {
		$prompt="$configDesc ($configFile)";
	}

	if (! exists $KeepConfig{"$configFile"})
	{
		$keep=system "diff $configFile $configFile-sample > /dev/null 2>&1";
		if ($keep != 0)
		{
			NormalPrint "You have a modified $configFile configuration file\n";
			$KeepConfig{"$configFile"} = GetYesNo("Do you want to keep $prompt?", "$default");
		} else {
			$KeepConfig{"$configFile"} = $keep;
		}
	}
	return $KeepConfig{"$configFile"};
}

# This is to update the old path when upgrading from 10.3 to newer version
sub replace_old_path_in($)
{
	my $filename = shift();
	open(FILE, "<$filename") || die "\nUnable to locate $filename\n";
	my @lines = <FILE>;
	close(FILE);

	# Replace /etc/sysconfig/opa/ with /etc/opa/
	my @newlines;
	foreach(@lines) {
		$_ =~ s/\/etc\/sysconfig\/opa\//\/etc\/opa\//g;
		push(@newlines,$_);
	}

	open(FILE, ">$filename") || die "\nUnable to locate $filename\n";
	print FILE @newlines;
	close(FILE);
}

# This subroutine is used to check if we should keep a modified rpm config file
# Optional second parameter used to check if a file exist in a previous (now deprecated)
# file location.
sub check_rpm_config_file($;$)
{
	my($config) = shift();
	my($old_config_dir) = shift();
	my($file_name) = basename($config);

	if ( $old_config_dir ne "" && !$Default_RpmConfigUseNew) {
		if ( -e "$old_config_dir/$file_name") {
			if ($Default_RpmConfigKeepOld || GetYesNo ("$file_name found in old file path $old_config_dir, move to new location?", "y")) {
				# This is to update the old path when upgrading from 10.3 to newer version
				replace_old_path_in ("$old_config_dir/$file_name");
				system "mv -f $old_config_dir/$file_name $config";
				return;
			}
		} elsif ( -e "$old_config_dir/$file_name.rpmsave") {
			if ($Default_RpmConfigKeepOld || GetYesNo ("$file_name.rpmsave found in old file path $old_config_dir, move to new location?", "y")) {
				# This is to update the old path when upgrading from 10.3 to newer version
				replace_old_path_in ("$old_config_dir/$file_name.rpmsave");
				system "mv -f $old_config_dir/$file_name.rpmsave $config";
				return;
			}
		}
	}

	if ( -e "$config.rpmsave") {
		if ($Default_RpmConfigKeepOld) {
			system "mv -f $config.rpmsave $config";
		} elsif ($Default_RpmConfigUseNew){
			system "rm -f $config.rpmsave";
		} elsif (GetYesNo ("Do you want to keep $config?", "y")) {
			system "mv -f $config.rpmsave $config";
		} else {
			system "rm -f $config.rpmsave";
		}
	} elsif ( -e "$config.rpmnew") {
		if ($Default_RpmConfigKeepOld) {
			system "rm -f $config.rpmnew";
		} elsif ($Default_RpmConfigUseNew){
			system "mv -f $config.rpmnew $config";
		} elsif (GetYesNo ("Do you want to keep $config?", "y")) {
			system "rm -f $config.rpmnew";
		} else {
			system "mv -f $config.rpmnew $config";
		}
	}
}

sub clear_keep_config($)
{
	my($configFile) = shift();

	delete $KeepConfig{"$configFile"};
}

sub remove_conf_file($$)
{
	my($WhichDriver) = shift();
	my($ConfFile) = shift();

	if (-e "$ConfFile") 
	{
		if (check_keep_config("$ConfFile", "$WhichDriver configuration file", "y"))
		{
			NormalPrint "Keeping $WhichDriver configuration file ($ConfFile) ...\n";
		} else {
			system "rm -rf $ConfFile";
		}
	}
	system "rm -rf ${ConfFile}-sample";
}

# remove a config file where a previous release used a different name for
# the file
sub remove_renamed_conf_file($$;@)
{
	my($WhichDriver) = shift();
	my($ConfFile) = shift();
	my(@OldConfFile_list) = @_;	# old config file names

	foreach my $OldConfFile ( @OldConfFile_list) {
		remove_conf_file("$WhichDriver", "$OldConfFile");
	}
	remove_conf_file("$WhichDriver", "$ConfFile");
}

sub install_conf_file($$$;@)
{
	my($WhichDriver) = shift();
	my($ConfFileDest) = shift();
	my($ConfFileSrc) = shift();
	my(@OldConfFileDest_list) = @_;	# optional
	my $diff_src_dest;
	my $diff_src_sample;
	my $diff_dest_sample;
	my $keep;
	my $need_copy = 1;

	# install an appropriate file into $ConfFileDest
	foreach my $OldConfFileDest ( @OldConfFileDest_list, $ConfFileDest ) {
		DebugPrint("Checking $OldConfFileDest\n");
		next if ( ! -e "$OldConfFileDest" );

		$diff_src_dest = system "diff $ConfFileSrc $OldConfFileDest > /dev/null 2>&1";

		if ( ! -e "${OldConfFileDest}-sample" )
		{
			DebugPrint("No ${OldConfFileDest}-sample\n");
			$diff_src_sample=1;
			$diff_dest_sample=1;
		} else {
			$diff_src_sample = system "diff $ConfFileSrc ${OldConfFileDest}-sample > /dev/null 2>&1";
			$diff_dest_sample = system "diff $OldConfFileDest ${OldConfFileDest}-sample > /dev/null 2>&1";
		}
		DebugPrint("Comparisons: src vs old=$diff_src_dest, src vs oldsample=$diff_src_sample, old vs oldsample=$diff_dest_sample\n");

		if ($diff_src_dest != 0)
		{
			if ($diff_dest_sample == 0)
			{
				NormalPrint "You have an unmodified $WhichDriver configuration file from an earlier install\n";
				$keep =check_keep_config("$OldConfFileDest", "", "n");
			} elsif ($diff_src_sample != 0)
			{
				NormalPrint "You have a $WhichDriver configuration file from an earlier install\n";
				$keep=check_keep_config("$OldConfFileDest", "", "y");
			} else {
				NormalPrint "You have a modified $WhichDriver configuration file\n";
				$keep=check_keep_config("$OldConfFileDest", "", "y");
			}
			if ( $keep ) {
				if ("$OldConfFileDest" ne "$ConfFileDest") {
					# we are working on an old config file
					copy_data_file("$OldConfFileDest", "$ConfFileDest");
					NormalPrint "Using $OldConfFileDest as $ConfFileDest...\n";
				} else {
					# we are working against the new supplied config file
					NormalPrint "Leaving $OldConfFileDest unchanged...\n";
				}
				$need_copy=0;
				last;
			} # otherwise onto next file, if needed will copy new file below
		}
	}
	if ( $need_copy) {
		# no old files kept (or not found), use new release version
		NormalPrint "Updating $ConfFileDest ...\n";
		copy_data_file("$ConfFileSrc", "$ConfFileDest");
	}
	foreach my $OldConfFileDest ( @OldConfFileDest_list ) {
		system "rm -rf ${OldConfFileDest}-sample";
	}
	copy_file("$ConfFileSrc", "${ConfFileDest}-sample", "$OWNER", "$GROUP", "ugo=r,u=r");
}

# after doing an rpm install, config files will be either installed (if new)
# or retained with the new version in .rpmnew
# this allows user to select which to keep as their present config file
sub copy_rpm_conf_file($$;@)
{
	my($WhichDriver) = shift();
	my($ConfFileDest) = shift();
	my(@OldConfFileDest_list) = @_;	# optional
	my($ConfFileSrc) = "$ConfFileDest.rpmnew";

	if ( ! -e "$ConfFileDest.rpmnew" )
	{
		# must be first install, Dest is the newest file
		# save a copy in case we overwrite it with an OldConfFileDest below
		system("cp $ConfFileDest $TMP_CONF");
		$ConfFileSrc="$TMP_CONF"
	}
	install_conf_file($WhichDriver, $ConfFileDest, $ConfFileSrc, @OldConfFileDest_list);
	system("rm -f $ConfFileSrc");
}

# After an RPM install, config files from previous install (denoted via .rpmsave)
# may need to be preserved. Ask the user if they want to keep.
sub preserve_prev_rpm_conf($)
{
	my($ConfFileDest) = shift();
	my($ConfFileSave) = "$ConfFileDest.rpmsave";
	
	if ( -e "$ConfFileSave" )
	{
		#install_conf_file($WhichDriver, $ConfFileDest, $ConfFileSave);
		#system("rm -f $ConfFileSave");
		my $diff_src_dest = system "diff $ConfFileDest $ConfFileSave > /dev/null 2>&1";
		if ($diff_src_dest != 0) {
			printf("You have a modified $ConfFileDest configuration file \n");
			my $keep = GetYesNo("Do you want to keep $ConfFileDest?", "y");
			if ($keep) {
				printf("Using the modified $ConfFileDest file \n");
				copy_data_file("$ConfFileSave", "$ConfFileDest");
			}
			else {
				printf("Using the new $ConfFileDest file \n");
			}
		}

		system "rm -f $ConfFileSave"
	}
}

# install a config file where a previous release used a different name for
# the file
sub install_renamed_conf_file($$$;@)
{
	my($WhichDriver) = shift();
	my($ConfFileDest) = shift();
	my($ConfFileSrc) = shift();
	my(@OldConfFileDest_list) = @_;	# in order that we consider them

	my $diff_src_dest;
	my $diff_src_sample;
	my $diff_dest_sample;

	if (! -e "$ConfFileDest") {
		# first upgrade install, we consider old files as relevant
		# we want to do the install_conf_file algorithm
		# but use OldConfFileDest for all but file destination of copy
		install_conf_file("$WhichDriver","$ConfFileDest","$ConfFileSrc",@OldConfFileDest_list);
	} else {
		# don't touch old (if any), just perform normal upgrade/install
		foreach my $OldConfFileDest ( @OldConfFileDest_list ) {
			system "rm -rf ${OldConfFileDest}-sample";
		}
		install_conf_file("$WhichDriver","$ConfFileDest","$ConfFileSrc");
	}
}

# ===========================================================================
# functions to insert/remove config file additions bounded by markers

# 
# Deletes contents from start marker to end marker
# arg0 : Start marker
# arg1 : End Marker
# arg2 : Leave Marks in file after removing contents
# arg3 : Filename to operate on
#

sub del_marks($$$$)
{
	my($StartMark) = shift();
	my($EndMark) = shift();
	my($LeaveMarks) = shift();
	my($FileName) = shift();

	my($found_mark)=0;

	open (INPUT, "$FileName");
	open (OUTPUT, ">>$TMP_CONF");

	select (OUTPUT);
	while (($found_mark == 0) && ($_=<INPUT>)) {
		if (/$StartMark/) {
			$found_mark=1;
			if ($LeaveMarks) {
				print $_;
			}
		} else {
			print $_;
		}
	}

	while (($found_mark == 1) && ($_=<INPUT>)) {
		if (/$EndMark/) {
			$found_mark = 0;
			if ($LeaveMarks) {
				print $_;
			}
		} 
	}

	while ($_=<INPUT>) {
		print $_;
	}

	select(STDOUT);

	close (INPUT);
	close (OUTPUT);

	system "mv $TMP_CONF $FileName";
}

# gets contents including marks and compares to specified file
# returns 0 on match, 1 if different
sub compare_marks($$$$)
{
	my($StartMark) = shift();
	my($EndMark) = shift();
	my($FileName) = shift();
	my($CompareTo) = shift();

	my $is_different;
	my $found_inf;

	system "awk '/$StartMark/, /$EndMark/ {print}' $FileName > /tmp/tmp.conf";
	$found_inf = `diff /tmp/tmp.conf $CompareTo`;
	system "rm -f /tmp/tmp.conf";

	if ($found_inf eq "") 
	{
		$is_different = 0;
	} else 
	{
		$is_different = 1;
	}
	return $is_different
}

# ===========================================================================
# functions to edit simple config files

# This function supports reading parameters from config file which are
# actually shell scripts.  openib.conf, opafastfabric.conf and the Linux network
# config files are examples of such.
# If the file or parameter does not exist, returns ""
sub read_simple_config_param($$)
{
	my $config_file=shift();
	my $parameter=shift();

	if ( ! -e "$config_file" ) {
		return "";
	}
	my $value=`. $config_file >/dev/null 2>/dev/null; echo \$$parameter`;
	chomp($value);
	return "$value";
}

sub edit_simple_config_file($$)
{
	my($FileName) = shift();
	my($changes) = shift();	# set of sed commands

	my $rc;

	$rc = system("sed $changes < $FileName > $TMP_CONF");
	if ($rc != 0) {
		system ("rm -rf $TMP_CONF >/dev/null 2>&1");
		return $rc;
	}

	$rc = system "mv $TMP_CONF $FileName";
	return $rc;
}

# ==========================================================================
# configuration file

# OFED & OPA configuration files are structured as a list of lines of the form:
# 	parameter=value
# There may be additional comment and whitespace lines
sub change_conf_param($$$)
{
	my $parameter=shift();
	my $newvalue=shift();
	my $conf=shift();

	VerbosePrint("edit $conf: '$parameter=$newvalue'\n");
	if (0 != system("grep '^$parameter=' $conf >/dev/null 2>/dev/null")) {
		# add parameter to file
		system ("echo '$parameter=$newvalue' >> $conf 2>/dev/null");;
	} else {
		return edit_simple_config_file("$conf",
			"-e 's/^$parameter=.*/$parameter=$newvalue/g'");
	}
}

sub change_openib_conf_param($$)
{
	my $p1=shift();
	my $p2=shift();
	change_conf_param($p1,$p2,"/$OFED_CONFIG");
}

sub change_opa_conf_param($$)
{
	my $p1=shift();
	my $p2=shift();
	change_conf_param($p1,$p2,"/$OPA_CONFIG");
}

sub read_openib_conf_param($$)
{
	my $parameter=shift();
	my $config_file=shift();	# if "", defaults to standard file

	if ( "$config_file" eq "" ) {
		$config_file="/$OFED_CONFIG";
	}
	return read_simple_config_param($config_file, $parameter);
}

sub read_opa_conf_param($$)
{
	my $parameter=shift();
	my $config_file=shift();	# if "", defaults to standard file

	if ( "$config_file" eq "" ) {
		$config_file="/$OPA_CONFIG";
	}
	return read_simple_config_param($config_file, $parameter);
}
# Function to setup environment variable. used to setup environment variables for RPM post install
# configuration
sub setup_env($$)
{
        my ($env_type) = shift();  # environment variable
        my ($env_value) = shift(); # value to be set
        $ENV{$env_type}="$env_value";
}

sub prompt_conf_param($$$$;$)
{
	my $parameter=shift();
	my $parameterDesc=shift();
	my $default=shift();
	my $conf=shift();
	my $OPA_INSTALL_ENV=shift();

	my $prompt;
	my $value;
	my $env_value;

	if ("$parameterDesc" eq "") {
		$prompt="$parameter";
	} else {
		$prompt="$parameterDesc ($parameter)";
	}
	if (GetYesNoWithMemory($parameter, 0, "Enable $prompt?", $default) == 1) {
		$value="yes";
		$env_value=1;
	} else {
		$value="no";
		$env_value=0;
	}
        # some configuation parameter are configured directly, some are by RPM. for RPM we will setup env variable.
        if ( $OPA_INSTALL_ENV eq "OPA_SRPHA_ENABLE" || $OPA_INSTALL_ENV eq "OPA_RENICE_IB_MAD" || $OPA_INSTALL_ENV eq "OPA_SET_IPOIB_CM" ) {
            change_conf_param($parameter, $value, $conf);
        } else {
            # setup env variable, RPM installation will configure these
           setup_env("$OPA_INSTALL_ENV", $env_value);
        }
}

sub prompt_openib_conf_param($$$;$)
{
	my $parameter=shift();
	my $parameterDesc=shift();
	my $default=shift();
	my $OPA_INSTALL_ENV=shift();

	prompt_conf_param($parameter, $parameterDesc, $default, 
		"/$OFED_CONFIG", $OPA_INSTALL_ENV);
}

sub prompt_opa_conf_param($$$;$)
{
	my $parameter=shift();
	my $parameterDesc=shift();
	my $default=shift();
	my $OPA_INSTALL_ENV=shift();

	prompt_conf_param($parameter, $parameterDesc, $default, 
		"/$OPA_CONFIG", $OPA_INSTALL_ENV);
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ===========================================================================
# startup scripts

# on Some Os's this configures startup file dependencies, especially for
# parallel startup optimizations
my $INSSERV_CONF="/etc/insserv.conf";
# where master copy of init scripts are installed
my $INIT_DIR = "/etc/init.d";
my $SYSTEMCTL_EXEC = system("command -v systemctl > /dev/null 2>&1");

sub disable_autostart($)
{
	my($WhichStartup) = shift();

	# disable autostart but leave any kill scripts so stopped on shutdown
	# Note on SLES off removes kill scripts too, on redhat they remain
	if($SYSTEMCTL_EXEC eq 0 && 
		($WhichStartup eq "opafm" || $WhichStartup eq "opa" || $WhichStartup eq "ibacm"))
	{
		system "systemctl disable $WhichStartup >/dev/null 2>&1";
	} else {
		system "/sbin/chkconfig $WhichStartup off > /dev/null 2>&1";
	}
}

sub enable_autostart($)
{
	my($WhichStartup) = shift();

	# cleanup to be safe
	if($SYSTEMCTL_EXEC eq 0 && 
		($WhichStartup eq "opafm" || $WhichStartup eq "opa" || $WhichStartup eq "ibacm"))
	{
		system "systemctl enable $WhichStartup >/dev/null 2>&1";
	} else {
		system "/sbin/chkconfig --del $WhichStartup > /dev/null 2>&1";
		system "/sbin/chkconfig --add $WhichStartup > /dev/null 2>&1";
		# make sure its enabled now
		system "/sbin/chkconfig $WhichStartup on > /dev/null 2>&1";
	}
}

# Is given startup script currently configured to autostart
sub IsAutostart($)
{
	my($WhichStartup) = shift();

	if($SYSTEMCTL_EXEC eq 0 &&
	   ($WhichStartup eq "opafm" || $WhichStartup eq "opa" || $WhichStartup eq "ibacm"))
	{
		my($isEnabled) = `systemctl is-enabled $WhichStartup 2>/dev/null`;
		chomp($isEnabled);
		if($isEnabled eq "disabled" || $isEnabled eq "")
		{
			return 0;
		} else {
			return 1;
		}
	} else {
		my $logoutput;
		open(CHKCONFIG,"/sbin/chkconfig --list $WhichStartup 2> /dev/null |") || Abort "Couldn't open a pipe for chkconfig\n";
		$logoutput = <CHKCONFIG>;
		close(CHKCONFIG);
		# remove startup name from output, this way opamon is not mistaken for "on"
		$logoutput=~s/^$WhichStartup//;
		if (grep /:on/, $logoutput)
		{
			return 1;
		} elsif ( `ls /etc/rc.d/rc3.d/S*$WhichStartup 2>/dev/null` ne "" ||
			`ls /etc/init.d/rc3.d/S*$WhichStartup 2>/dev/null` ne "") {
			# this case is an old install being updated.
			# A SLES OS may have no link from init.d to rc.d. So we check init.d folder as well.
			return 1;
		} else {
			return 0;
		}
	}
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ============================================================================
# Driver file management

my $RunDepmod=0;	# do we need to run depmod
sub	verify_modtools()
{
	my $look_str;
	my $look_len;
	my $ver;
	my $mod_ver;

	$look_str = "insmod version ";
	$look_len = length ($look_str);
	$ver = `/sbin/insmod -V 2>&1 | grep \"$look_str\"`;
	chomp $ver;
	$mod_ver = substr ($ver, $look_len - 1, length($ver)-$look_len+1);
	$_ = $mod_ver;
	/2\.[34]\.[0-9]+/;
	#$MOD_UTILS_REV;
	if ($& eq "")
	{
		NormalPrint "Unable to proceed, modutils tool old: $mod_ver\n";
		Abort "Install newer version of modutils 2.3.15 or greater" ;
	}
}

# the following two routines are used for STL-14186. hfi2 rpm doesn't call depmod on uninstall, so we need to explicitly
# call it when we uninstall opa_stack. After we resolve the issue, we shall remove the following 2 routines
sub clear_run_depmod()
{
	$RunDepmod=0;
}

sub set_run_depmod()
{
	$RunDepmod=1;
}

sub check_depmod()
{
	if ($RunDepmod == 1 )
	{
		print_separator;
		print "Generating module dependencies...\n";
		LogPrint "Generating module dependencies: /sbin/depmod -aev\n";
		system "/sbin/depmod -aev > /dev/null 2>&1";
		$RunDepmod=0;
		return 1;
	}
	return 0;
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# =========================================================================
# Component installation state

# constants for component state/action tracking during menus
my $State_Uninstall = 0;
my $State_Install = 1;
my $State_UpToDate = 2;
my $State_DoNotInstall = 3;
my $State_DoNotAutoInstall = 4;	# valid only in DefaultInstall, must explicitly select

sub disable_components(@);
my %comp_prereq_hash;
# indicate if given state reflects a component which will be on the system
# after processing the present menu selections
# states:
# $State_Uninstall - make sure not on system (Uninstall)
# $State_Install - install on system (Install/Upgrade/Re-Install)
# $State_UpToDate - leave as is on system (Installed/Up To Date)
# $State_DoNotInstall - leave as is not on system (Do Not Install)
sub will_be_on_system($)
{
	my $state = shift();

	return ($state == $State_Install || $state == $State_UpToDate);
}

# state returned:
# $State_Uninstall - make sure not on system (Uninstall)
# $State_Install - install on system (Install/Upgrade/Re-Install)
# $State_UpToDate - leave as is on system (Installed/Up To Date)
# $State_DoNotInstall - leave as is not on system (Do Not Install)
sub setstate($$$$)
{
	my $isinstalled = shift();   
	my $available   = shift();
	my $isupgrade   = shift();
	my $defaultstate= shift();	# default if available and ! installed

	if (! $available && $isinstalled && !$isupgrade){ return $State_UpToDate; }
	if (! $available && ! $isinstalled )			{ return $State_DoNotInstall; }
	if (! $available )				                { return $State_Uninstall; }
	if ($isinstalled && !$isupgrade)				{ return $State_UpToDate; }
	if ($isinstalled)								{ return $State_Install; }
	# available and not installed
	if ($defaultstate == $State_DoNotAutoInstall)	{ return $State_DoNotInstall; }
	return $defaultstate;	# typcally State_Install
}

# state returned:
# $State_Uninstall - make sure not on system (Uninstall)
# $State_Install - install on system (Install/Upgrade/Re-Install)
# $State_UpToDate - leave as is on system (Installed/Up To Date)
# $State_DoNotInstall - leave as is not on system (Do Not Install)
sub shiftstate($$$$)
{
	my $state       = shift();
	my $isinstalled = shift();   
	my $available   = shift();
	my $isupgrade   = shift();

	if (! $available && $isinstalled && ! $isupgrade) {
		return ($state==$State_UpToDate)?$State_Uninstall:$State_UpToDate;
	}
	if (! $available && ! $isinstalled ) {
		return ($state==$State_DoNotInstall)?$State_Uninstall:$State_DoNotInstall;
	}
	if (! $available ) {
		return $State_Uninstall;
	}
	if ($isinstalled && !$isupgrade) {
		return ($state==$State_UpToDate)?$State_Install
				:($state==$State_Install)?$State_Uninstall
				:$State_UpToDate;
	}
	if ($isinstalled ) {
		return ($state==$State_Install)?$State_Uninstall:$State_Install;
	}
	# available and not installed
	return ($state==$State_Uninstall)?$State_Install
			:($state==$State_Install)?$State_DoNotInstall:$State_Uninstall;
}

sub InstallStateToStr($)
{
	my $state = shift();

	if ($state == $State_Uninstall) {
		return "Uninstall";
	} elsif ($state == $State_Install) {
		return "Install";
	} elsif ($state == $State_UpToDate) {
		return "UpToDate";
	} elsif ($state == $State_DoNotInstall) {
		return "DoNotInstall";
	} elsif ($state == $State_DoNotAutoInstall) {
		return "DoNotAutoInstall";
	} else {
		return "INVALID";
	}
}

# caller has output 24 characters, we have 55 left to play with
# (avoid using last column so don't autowrap terminal)
sub printInstallState($$$$)
{
	my $installed = shift();
	my $uninstall = shift();
	my $boldmessage = shift();
	my $message   = shift();

	if ($uninstall )
	{
		print   RED, "[  Uninstall  ] ", RESET;
	} elsif ($installed ) {
		print GREEN, "[  Installed  ] ", RESET;
	} else {
		print        "[Not Installed] ";
	}
	if ("$message" ne "" && $boldmessage) {
		print BOLD, RED "$message", RESET, "\n";
	} else {
		print "$message\n";
	}
	return;
}

# states:
# $State_Uninstall - make sure not on system (Uninstall)
# $State_Install - install on system (Install/Upgrade/Re-Install)
# $State_UpToDate - leave as is on system (Installed/Up To Date)
# $State_DoNotInstall - leave as is not on system (Do Not Install)
sub printInstallAvailableState($$$$$$)
{
	my $installed = shift();
	my $available = shift();
	my $isupgrade = shift();
	my $state     = shift();
	my $boldmessage = shift();
	my $message   = shift();

	if ( $state == $State_Uninstall )
	{
		print RED, "[  Uninstall  ]", RESET;
	} elsif ( $state == $State_Install) {
		if ($installed)
		{           
			if ( $isupgrade ) 
			{       
				print GREEN, "[   Upgrade   ]", RESET;
			} else {
				print "[ Re-Install  ]";
			}
		} else {
			print           "[   Install   ]";
		}
	} elsif ($state == $State_UpToDate) {
		print "[ Up To Date  ]";
	} elsif ($state == $State_DoNotInstall) {
		print "[Don't Install]";
	}

	if ( $available )
	{
		print "[Available] ";
	} else {
		print BOLD, RED "[Not Avail] ", RESET;
	}
	if ("$message" ne "" && $boldmessage) {
		print BOLD, RED "$message", RESET, "\n";
	} else {
		print "$message\n";
	}

	return;
}

# =======================================================================
# Component processing

# function must be supplied if any components set ComponentInfo{}{HasFirmware}

# these variables must be initialized by main program to control the
# data driven component menus and functions in this section
my $Default_Install=0;	# -a option used to select default install of All
my $Default_Upgrade=0;	# -U option used to select default upgrade of installed
my $Default_Uninstall=0;	# -u option used to select default uninstall of All
my $Default_SameAutostart=0; # -n option used to default install, preserving autostart values
my $Default_CompInstall=0;	# -i option used to select default install of Default_Components
my $Default_CompUninstall=0;	# -e option used to select default uninstall of Default_Components
my %Default_Components = ();		# components selected by -i or -e
my $Skip_FirmwareUpgrade=1;	# -f option used to select skipping firmware upgrade
my $Default_Autostart=0;	# -s option used to select default autostart of All
my $Default_DisableAutostart=0; # -D option used to select default disabling of autostart for Default_DisabledComponents
my %Default_DisabledComponents = ();		# components selected by -D
my $Default_EnableAutostart=0; # -E option used to select default enabling of autostart for Default_EnabledComponents
my %Default_EnabledComponents = ();		# components selected by -E
my $Default_ShowCompInfo=0; # -c option used to select default component information display of Default_Components

	# Names of supported install components
	# must be listed in depdency order such that prereqs appear 1st
my @Components = ();

# Sub components for autostart processing
my @SubComponents = ();

# components/subcomponents for autostart processing
my @AutostartComponents = ();

	# an additional "special" component which is always installed when
	# we install/upgrade anything and which is only uninstalled when everything
	# else has been uninstalled.  Typically this will be the opaconfig
	# file and related files absolutely required by it (such as wrapper_version)
my $WrapperComponent = "";

# This provides more detailed information about each Component in @Components
# since hashes are not retained in the order specified, we still need
# @Components and @SubComponents to control install and menu order
# Only items listed in @Components and @SubComponents are considered for install
# As such, this may list some components which are N/A to the selected distro
# Fields are as follows:
#	Name => full name of component/subcomponent for prompts
# 	DefaultInstall => default installation (State_DoNotInstall,
# 					  State_DoNotAutoInstall or State_Install)
#					  used only when available and ! installed
#	SrcDir => directory name within install media for component
# 	PreReq => other components which are prereqs of a given
#				component/subcomponent
#				Need space before and after each component name to
#				facilitate compares so that compares do not mistake names
#				such as mpidev for mpi
#	CoReq =>  other components which are coreqs of a given component
#				Note that CoReqs can also be listed as prereqs to provide
#				install verification as each component is installed,
#				however prereqs should only refer to items earlier in the list
#				Need space before and after each component name to
#				facilitate compares so that compares do not mistake names
#				such as mpidev for mpi
#	Hidden => component should not be shown in menus/prompts
#			  used for hidden PreReq.  Hidden components can't HasStart
#			  nor HasFirmware
#	Disabled =>  components/subcomponents which are disabled from installation
#	IsOFA =>  is an in-distro OFA component we upgrade (excludes MPI)
#	KernelRpms => kernel rpms for given component, in dependency order
#				These are rpms which are kernel version specific and
#				will have kernel uname -r in rpm package name.
#				For a given distro a separate version of each of these rpms
#				may exist per kernel.  These are always architecture dependent
#				Note KernelRpms are always installed before FirmwareRpms and
#				UserRpms
#	FirmwareRpms => firmware rpms for given component, in dependency order
#				These are rpms which are not kernel specific.  For a given
#				distro a single version of each of these rpms will
#				exist per distro/arch combination.  In most cases they will
#				be architecture independent (noarch).
#				These are rpms which are installed in user space but
#				ultimately end up in hardware such as HFI firmware, TMM firmware
#				BIOS firmware, etc.
#	UserRpms => user rpms for given component, in dependency order
#				These are rpms which are not kernel specific.  For a given
#				distro a single version of each of these rpms will
#				exist per distro/arch combination.  Some of these may
#				be architecture independent (noarch).
#	DebugRpms => user rpms for component which should be installed as part
#				of delta_debug component.
#	HasStart =>  components/subcomponents which have autostart capability
#	DefaultStart =>  should autostart default to Enable (1) or Disable (0)
#				Not needed/ignored unless HasStart=1
# 	StartPreReq => other components/subcomponents which must be autostarted
#				before autostarting this component/subcomponent
#				Not needed/ignored unless HasStart=1
#				Need space before and after each component name to
#				facilitate compares so that compares do not mistake names
#				such as mpidev for mpi
#	StartComponents => components/subcomponents with start for this component
#				if a component has a start script 
#				list the component as a subcomponent of itself
#	StartupScript => name of startup script which controls startup of this
#				component
#	StartupParams => list of parameter names in $OPA_CONFIG which control
#				startup of this component (set to yes/no values)
#	HasFirmware =>  components which need HCA firmware update after installed
#
# Note both Components and SubComponents are included in the list below.
# Components require all fields be supplied
# SubComponents only require the following fields:
#	Name, PreReq (should reference only components), HasStart, StartPreReq,
#	DefaultStart, and optionally StartupScript, StartupParams
#	Also SubComponents only require the IsAutostart2_X, autostart_desc_X,
#	enable_autostart2_X, disable_autostart2_X and installed_X functions.
#	Typically installed_X for a SubComponent will simply call installed_X for
#	the component which contains it.
my %ComponentInfo = ();
	# translate from startup script name to component/subcomponent name
my %StartupComponent = ();
	# has component been installed since last configured autostart
my %ComponentWasInstalled = ();

my %ExtraMpisrcInfo = ();

# constants for autostart functions $configure argument
my $Start_Unspecified=0;
my $Start_NoStart=1;
my $Start_Start=2;

sub ShowComponents(;$)
{
	my $print_param = shift || \*STDOUT; #STDOUT as default parameter
	foreach my $comp ( @Components )
	{
		if (! $ComponentInfo{$comp}{'Hidden'}) {
			print $print_param " $comp";
		}
	}
	print $print_param "\n";
}

sub ShowCompInfo(;$)
{
	my $print_param = shift || \*STDOUT; #STDOUT as default parameter
	print $print_param "[\n";
	my $first_comp = 1;
	my $first_item = 1;
	foreach my $comp ( @Components )
	{
		if ( $Default_Components{$comp} ) {
			if ($first_comp == 1) {
				$first_comp = 0;
				print $print_param " {\n";
			} else {
				print $print_param ",\n {\n";
			}
			print $print_param "  \"ID\": \"$comp\",\n";
			my $name = $ComponentInfo{$comp}{'Name'};
			print $print_param "  \"Name\": \"$name\",\n";
			if ( $comp eq "delta_debug" ) {
				print $print_param "  \"error\": \"Not apply. We ship debug rpms in meta pkg <component>_debuginfo.\"\n";
				print $print_param " },\n";
				next;
			}
			if (comp_is_available($comp)) {
				print $print_param "  \"Available\": \"yes\",\n";
			} else {
				print $print_param "  \"Available\": \"no\",\n";
			}
			my $full_ver = comp_media_version($comp);
			my ($version, $release) = GetVerRel($full_ver);
			print $print_param "  \"Version\": \"$version\",\n";
			print $print_param "  \"Release\": \"$release\",\n";
			print $print_param "  \"PreReq\": [\n";
			$first_item = 1;
			my @reqs = split(/ /, $ComponentInfo{$comp}{'PreReq'});
			foreach my $req (@reqs) {
				# ignore req that is not a component. This is for the case we do not
				# have mpi_selector for SLES
				if ( $req ne '' && grep( /^$req$/, @Components) ) {
					my $reqver = comp_media_version($req);
					my ($version, $release) = GetVerRel($reqver);
					$reqver = "$version-$release";
					if ($first_item == 1) {
						$first_item = 0;
						print $print_param "   {\"ID\": \"$req\", \"Version\": \"$reqver\"}";
					} else {
						print $print_param ",\n   {\"ID\": \"$req\", \"Version\": \"$reqver\"}";
					}
				}
			}
			print $print_param "\n  ],\n";
			@reqs = split(/ /, $ComponentInfo{$comp}{'CoReq'});
			print $print_param "  \"CoReq\": [\n";
			$first_item = 1;
			foreach my $req (@reqs) {
				# ignore req that is not a component. This is for the case we do not
				# have mpi_selector for SLES
				if ( $req ne '' && grep( /^$req$/, @Components) ) {
					my $reqver = comp_media_version($req);
					my ($version, $release) = GetVerRel($reqver);
					$reqver = "$version-$release";
					if ($first_item == 1) {
						$first_item = 0;
						print $print_param "   {\"ID\": \"$req\", \"Version\": \"$reqver\"}";
					} else {
						print $print_param ",\n   {\"ID\": \"$req\", \"Version\": \"$reqver\"}";
					}
				}
			}
			print $print_param "\n  ],\n";
			if ( $comp eq "mpisrc" ) {
				print $print_param "  \"SrcRpms\": {\n";
				my $destdir = $ExtraMpisrcInfo{'Dest'};
				print $print_param "   \"Dest\": \"$destdir\",\n";
				my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'};
				print $print_param "   \"Source\": \"$srcdir\",\n";
				print $print_param "   \"Resources\": [\n";
				$first_item = 1;
				foreach my $srpm (@{$ExtraMpisrcInfo{'SrcRpms'}}) {
					my $srpmfile = file_glob("$srcdir/${srpm}-*.src.rpm");
					if ( "$srpmfile" ne "" ) {
						my $file = my_basename($srpmfile);
						if ($first_item == 1) {
							$first_item = 0;
							print $print_param "    \"$file\"";
						} else {
							print $print_param ",\n    \"$file\"";
						}
					}
				}
				print $print_param "\n   ]\n";
				print $print_param "  },\n";
				print $print_param "  \"BuildScripts\": {\n";
				print $print_param "   \"Dest\": \"$destdir\",\n";
				print $print_param "   \"Source\": \"$srcdir\",\n";
				print $print_param "   \"Resources\": [\n";
				$first_item = 1;
				foreach my $script (@{$ExtraMpisrcInfo{'BuildScripts'}}) {
					if ($first_item == 1) {
						$first_item = 0;
						print $print_param "    \"$script\"";
					} else {
						print $print_param ",\n    \"$script\"";
					}
				}
				print $print_param "\n   ]\n";
				print $print_param "  },\n";
				print $print_param "  \"MiscFiles\": [\n";
				$first_item = 1;
				foreach my $file (@{$ExtraMpisrcInfo{'MiscFiles'}}) {
					my $src = ${$file}{'Src'};
					my $dest = ${$file}{'Dest'};
					if ($first_item == 1) {
						$first_item = 0;
					} else {
						print $print_param ",\n";
					}
					print $print_param "    {\"Dest\": \"$destdir/$dest\", \"Src\": \"$srcdir/$src\"}";
				}
				print $print_param "\n  ],\n";
				print $print_param "  \"DirtyFiles\": {\n";
				print $print_param "   \"Dest\": \"$destdir\",\n";
				print $print_param "   \"Source\": \"\",\n";
				print $print_param "   \"Resources\": [\n";
				$first_item = 1;
				foreach my $file (@{$ExtraMpisrcInfo{'DirtyFiles'}}) {
					if ($first_item == 1) {
						$first_item = 0;
						print $print_param "    \"$file\"";
					} else {
						print $print_param ",\n    \"$file\"";
					}
				}
				print $print_param "\n   ]\n";
				print $print_param "  }\n";
			} else {
				print $print_param "  \"UserRpms\": [\n";
				ShowRpmList($print_param, "   ", "user", @{$ComponentInfo{$comp}{'UserRpms'}});
				print $print_param "\n  ],\n";
				print $print_param "  \"KernelRpms\": [\n";
				ShowRpmList($print_param, "   ", $CUR_OS_VER, @{$ComponentInfo{$comp}{'KernelRpms'}});
				print $print_param "\n  ],\n";
				print $print_param "  \"FirmwareRpms\": [\n";
				ShowRpmList($print_param, "   ", "firmware", @{$ComponentInfo{$comp}{'FirmwareRpms'}});
				print $print_param "\n  ],\n";
				print $print_param "  \"DebugTpms\": [\n";
				ShowRpmList($print_param, "   ", "any", @{$ComponentInfo{$comp}{'DebugRpms'}});
				print $print_param "\n  ]\n";
			}

			print $print_param " }";
		}
	}
	print $print_param "\n]\n";
}

sub GetVerRel($)
{
	my $full_ver = shift();
	my ($version, $release) = split('-', $full_ver, 2);
	if ("$release" eq "") {
		# assume the version is in expected format, and it shall be.
		my @segs = split('\.', $version);
		my $last = scalar(@segs)-1;
		$version = join('.', @segs[0..3]);
		$release = join('.', @segs[4..$last]);
	}
	return ($version, $release);
}

sub ShowRpmList($$$$@)
{
	my $print_param = shift();
	my $prefix = shift();
	my $mode = shift();
	my @rpms = @_;
	my $rpmsdir = "";
	my $first_item = 1;
	foreach my $rpm (@rpms) {
		if ( $GPU_Install && -d file_glob("./repos/OPA_PKGS_CUDA") ) {
			$rpmsdir=file_glob("./repos/OPA_PKGS_CUDA/RPMS");
		} else {
			$rpmsdir=file_glob("./repos/OPA_PKGS/RPMS");
		}
		my $rpm_file = rpm_resolve("$rpmsdir/$rpm", $mode);
		if ( $rpm_file ne '' ) {
			my $version = rpm_query_version_release($rpm_file);
			my $epoch = rpm_query_attr($rpm_file, "EPOCH");
			if ("$epoch" ne "") {
				$version = "$epoch:$version";
			}
			if ($first_item == 1) {
				$first_item = 0;
				print $print_param "$prefix\{\"ID\": \"$rpm\", \"Version\": \"$version\"}";
			} else {
				print $print_param ",\n$prefix\{\"ID\": \"$rpm\", \"Version\": \"$version\"}";
			}
		} else {
			DebugPrint "Not found $rpm";
		}
	}
}

# return 1 if $comp has a prereq of $prereq, 0 otherwise
sub comp_has_prereq_of($$)
{
	my($comp) = shift();
	my($prereq) = shift();

	if ($ComponentInfo{$comp}{'PreReq'} =~ / $prereq /) {
		return 1;
	} else {
		return 0;
	}
}

# return 1 if $comp has a coreq of $coreq, 0 otherwise
sub comp_has_coreq_of($$)
{
	my($comp) = shift();
	my($coreq) = shift();

	if ($ComponentInfo{$comp}{'CoReq'} =~ / $coreq /) {
		return 1;
	} else {
		return 0;
	}
}

# return 1 if $comp has a prereq or coreq of $req, 0 otherwise
sub comp_has_req_of($$)
{
	my($comp) = shift();
	my($req) = shift();

	return (comp_has_prereq_of($comp, $req) || comp_has_coreq_of($comp, $req));
}
# return 1 if $comp has a prereq of $prereq, 0 otherwise
sub comp_has_startprereq_of($$)
{
	my($comp) = shift();
	my($prereq) = shift();

	if ($ComponentInfo{$comp}{'StartPreReq'} =~ / $prereq /) {
		return 1;
	} else {
		return 0;
	}
}

# package is supplied since for a few packages (such as GPU Direct specific
# packages) we may pick a different directory based on package name
sub comp_get_rpms_dir($$)
{
	my $comp = shift();
	my $package = shift();
	return eval "get_rpms_dir_$comp('$package')";
}

# for comp_is_available we specially handle the case of function not found
# in which case eval returns ""
# all other component functions against install media will have called
# comp_is_available first, so they need not be protected by this test
sub comp_is_available($)
{
	my $comp = shift();
	my $rc;

	if ($ComponentInfo{$comp}{'Disabled'}) {
		return 0;
	}
	$rc = eval "available_$comp()";
	if ( "$rc" eq "" ) {
		return 0;	# $comp not loaded
	} else {
		return $rc;
	}
}

# return version string for component on install media
# only valid if comp_is_available is TRUE
sub comp_media_version($)
{
	my $comp = shift();

	my $result = eval "media_version_$comp()";
	chomp $result;
	return $result;
}

# for comp_is_installed we specially handle the case of function not found
# in which case eval returns ""
# all other component functions against system itself will have called
# comp_is_installed first, so they need not be protected by this test
sub comp_is_installed($)
{
	my $comp = shift();
	my $rc;

	$rc = eval "installed_$comp()";
	if ( "$rc" eq "" ) {
		return 0;	# $comp not loaded
	} else {
		return $rc;
	}
}

# return version string for component on system
# only valid if comp_is_installed is TRUE
sub comp_installed_version($)
{
	my $comp = shift();

	my $result = eval "installed_version_$comp()";
	chomp $result;
	return $result;
}

# return TRUE if component is installed and up to date
# return FALSE if not installed, or not same version as media
# typically only called when component is available, returns
# FALSE if component not available
sub comp_is_uptodate($)
{
	my $comp = shift();

	# safety check
	if (! comp_is_available("$comp") ) {
		return 0;
	}
	if (! comp_is_installed("$comp")) {
		return 0;
	}
	# available and installed, compare versions
	return (comp_installed_version($comp) eq comp_media_version($comp));
}

# check if all prereqs of $comp have been installed
# returns: 1 - all ok, 0 - some prereqs missing
sub check_prereqs($)
{
	my($comp) = shift();

	foreach my $c ( @Components )
	{
		if (comp_has_prereq_of($comp, $c) && ! comp_is_installed("$c") )
		{
			NormalPrint "Unable to Install $ComponentInfo{$comp}{'Name'}, prereq $ComponentInfo{$c}{'Name'} not installed\n";
			HitKeyCont;
			return 0;
		}
	}
	return 1;
}

# build processing for the given component
# returns 0 on success, 1 on failure
# only valid if comp_is_available is TRUE
sub comp_build($$$$$)
{
	my $comp = shift();
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild

	LogPrint "Building $ComponentInfo{$comp}{'Name'} for $osver using '$build_temp'\n";
	return eval "build_$comp('$osver',$debug,'$build_temp',$force)";
}

# special hook for build processing for the given component within OFED build
# returns 1 if build should be done, 0 if not
# only valid for subset of components and if comp_is_available is TRUE
sub comp_ofed_need_build($$$$)
{
	my $comp = shift();
	my $osver = shift();
	my $force = shift();	# should we force build
	my $prompt = shift();	# should we prompt user about build

	return eval "ofed_need_build_$comp('$osver',$force,$prompt)";
}

# special hook for build processing for the given component within OFED build
# returns 0 on success, >0 on failure
# only valid for subset of components and if comp_is_available is TRUE
sub comp_ofed_check_build_dependencies($$)
{
	my $comp = shift();
	my $osver = shift();

	return eval "ofed_check_build_dependencies_$comp('$osver')";
}

# special hook for build processing for the given component within OFED build
# returns 0 on success, 1 on failure
# only valid for subset of components and if comp_is_available is TRUE
sub comp_ofed_build($$$$)
{
	my $comp = shift();
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build

	LogPrint "Building $ComponentInfo{$comp}{'Name'} for $osver using '$build_temp'\n";
	return eval "ofed_build_$comp('$osver',$debug,'$build_temp')";
}

# before preinstall determine if present settings will require all
# installed components to be reinstalled
# returns "all" if need to reinstall all UpToDate components
# returns "this" if need to reinstall this component even if up to date
# returns "no" if no need to reinstall this component even if up to date
# only valid if comp_is_available is TRUE
sub comp_need_reinstall($$$)
{
	my $comp = shift();
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return eval "need_reinstall_$comp('$install_list', '$installing_list')";
}

# check presence of OS prereqs for the given component
# returns 0 on success, 1 on failure
# only valid if comp_is_available is TRUE
# for backward compatibility with old comp.pl files
# we specially handle the case of function not found
# in which case eval returns ""
sub comp_check_os_prereqs($)
{
	my $comp = shift();
	my $rc;

	DebugPrint "Checking OS Prereqs for $ComponentInfo{$comp}{'Name'}\n";
	$rc = eval "check_os_prereqs_$comp()";
	DebugPrint "Done: rc='$rc'\n";
	if ( "$rc" eq "" ) {
		return 0;	# $comp not loaded
	} else {
		return $rc;
	}
}

# preinstall processing for the given component
# returns 0 on success, 1 on failure
# only valid if comp_is_available is TRUE
sub comp_preinstall($$$)
{
	my $comp = shift();
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return eval "preinstall_$comp('$install_list', '$installing_list')";
}

# install the given component
# only valid if comp_is_available is TRUE
sub comp_install($$$)
{
	my $comp = shift();
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	# sanity check, should not get here if false
	if (! comp_is_available($comp) ) {
		$exit_code = 1;
		return;
	}
	print_separator;
	# this will catch failures in install of prereqs
	if (! check_prereqs($comp)) {
		$exit_code = 1;
		return;
	}

	eval "install_$comp('$install_list', '$installing_list')";
}

# postinstall processing for the given component
# only valid if comp_is_available is TRUE
sub comp_postinstall($$$)
{
	my $comp = shift();
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	eval "postinstall_$comp('$install_list', '$installing_list')";
}

# uninstall the given component
# typically only called if comp_is_available is TRUE
# or comp_is_installed is TRUE
# however could be called when not available and not installed in which
# case could be an empty function, in which case we can simply ignore
# eval's "" return
sub comp_uninstall($$$)
{
	my $comp = shift();
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_separator;
	if ($ComponentInfo{$comp}{'HasStart'}) {
		disable_components(@{ $ComponentInfo{$comp}{'StartComponents'} });
	}
	eval "uninstall_$comp('$install_list', '$uninstalling_list')";
}

# determine if the given component is configured for Autostart at boot
sub comp_IsAutostart2($)
{
	my $comp = shift();

	return eval "IsAutostart2_$comp()";
}
# get autostart desc for the given component
sub comp_autostart_desc($)
{
	my $comp = shift();

	my $desc = eval "autostart_desc_$comp()";
	if ( "$desc" eq "" ) {
		$desc = $ComponentInfo{$comp}{'Name'};
	}
	return $desc;
}
# enable autostart for the given component
sub comp_enable_autostart2($$)
{
	my $comp = shift();
	my $quiet = shift();

	if ( ! comp_IsAutostart2($comp) == 1 )
	{
		if (! $quiet) {
			my $desc = comp_autostart_desc($comp);
			NormalPrint "Enabling autostart for $desc\n";
		}
	}
	eval "enable_autostart2_$comp()";
}
# disable autostart for the given component
sub comp_disable_autostart2($$)
{
	my $comp = shift();
	my $quiet = shift();

	if ( comp_IsAutostart2($comp) == 1 )
	{
		if (! $quiet) {
			my $desc = comp_autostart_desc($comp);
			NormalPrint "Disabling autostart for $desc\n";
		}
	}

	eval "disable_autostart2_$comp()";
}

sub DumpComponents($)
{
	my $allow_install = shift();

	if (! DebugPrintEnabled() ) {
		return;
	}
	DebugPrint("\nComponents:\n");
	foreach my $comp ( @Components, "mpiRest" ) {
		DebugPrint("   $comp: '$ComponentInfo{$comp}{'Name'}' SrcDir: $ComponentInfo{$comp}{'SrcDir'}\n");
		DebugPrint("           DefaultInstall: ".InstallStateToStr($ComponentInfo{$comp}{'DefaultInstall'})."\n");
		DebugPrint("           PreReq: $ComponentInfo{$comp}{'PreReq'} CoReq: $ComponentInfo{$comp}{'CoReq'}\n");
		DebugPrint("           Hidden: $ComponentInfo{$comp}{'Hidden'} Disabled: $ComponentInfo{$comp}{'Disabled'} HasFirmware: $ComponentInfo{$comp}{'HasFirmware'} IsOFA: $ComponentInfo{$comp}{'IsOFA'}\n");
		DebugPrint("           KernelRpms: @{ $ComponentInfo{$comp}{'KernelRpms'}}\n");
		DebugPrint("           FirmwareRpms @{ $ComponentInfo{$comp}{'FirmwareRpms'}}\n");
		DebugPrint("           UserRpms: @{ $ComponentInfo{$comp}{'UserRpms'}}\n");
		DebugPrint("           DebugRpms: @{ $ComponentInfo{$comp}{'DebugRpms'}}\n");
		DebugPrint("           HasStart: $ComponentInfo{$comp}{'HasStart'} DefaultStart: $ComponentInfo{$comp}{'DefaultStart'}\n");
		DebugPrint("           StartPreReq: $ComponentInfo{$comp}{'StartPreReq'} StartComponents: @{ $ComponentInfo{$comp}{'StartComponents'}}\n");
		DebugPrint("           StartupScript: $ComponentInfo{$comp}{'StartupScript'} StartupParams: @{ $ComponentInfo{$comp}{'StartupParams'}}\n");
		if ($allow_install) {
			my $avail = comp_is_available($comp);
			DebugPrint("           IsAvailable: $avail");
			if ($avail) {
				DebugPrint("           MediaVersion: ".comp_media_version($comp));
			}
			DebugPrint("\n");
		}
		my $installed = comp_is_installed($comp);
		DebugPrint("           IsInstalled: $installed");
		if ($installed) {
			DebugPrint("           InstalledVersion: ".comp_installed_version($comp));
		}
		DebugPrint("\n");
	}

	DebugPrint("\nSubComponents:\n");
	foreach my $comp ( @SubComponents ) {
		DebugPrint("   $comp: '$ComponentInfo{$comp}{'Name'}'\n");
		DebugPrint("           PreReq: $ComponentInfo{$comp}{'PreReq'} CoReq: $ComponentInfo{$comp}{'CoReq'}\n");
		DebugPrint("           HasStart: $ComponentInfo{$comp}{'HasStart'}\n");
		DebugPrint("           StartPreReq: $ComponentInfo{$comp}{'StartPreReq'}\n");
		DebugPrint("           StartupScript: $ComponentInfo{$comp}{'StartupScript'} StartupParams: @{ $ComponentInfo{$comp}{'StartupParams'}}\n");
	}
}

# output standard banner for component install
# This function can be called within a components install_X function
sub print_comp_install_banner($)
{
	my $comp = shift();

	my $version=comp_media_version($comp);
	chomp $version;
	printf("Installing $ComponentInfo{$comp}{'Name'} $version $DBG_FREE...\n");
	LogPrint "Installing $ComponentInfo{$comp}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER $CUR_OS_VER\n";
}

# install the given list of rpms for a component
sub install_comp_rpm_list($$$@)
{
	my $comp = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
	my $options = shift();	# additional rpm command options
	my @package_list = @_;	# package names

	my @rpmpath_list = ();

	foreach my $package ( @package_list )
	{
		my $rpmsdir=comp_get_rpms_dir($comp, $package);
		@rpmpath_list = ( @rpmpath_list, "$rpmsdir/$package" );
	}
	rpm_install_path_list_with_options($mode, "$options", @rpmpath_list);
}

# helper which does most of the work for installing rpms for a component
# This function can be called within a components install_X function
# installs KernelRpms, FirmwareRpms and UserRpms
# caller must handle any non-RPM files
sub install_comp_rpms($$$)
{
	my $comp = shift();
	my $options = shift();	# additional rpm command options
	my $install_list = shift();	# total that will be installed when done

	if (! $user_space_only ) {
		install_comp_rpm_list($comp, $CUR_OS_VER, "$options",
								@{ $ComponentInfo{$comp}{'KernelRpms'}} );
		install_comp_rpm_list($comp, "firmware", "$options",
								@{ $ComponentInfo{$comp}{'FirmwareRpms'}} );
	}
	install_comp_rpm_list($comp, "user", "$options",
								@{ $ComponentInfo{$comp}{'UserRpms'}} );
	# DebugRpms are installed as part of 'delta_debug' component
}

# output standard banner for component uninstall
# This function can be called within a components install_X function
sub print_comp_uninstall_banner($)
{
	my $comp = shift();

	NormalPrint("Uninstalling $ComponentInfo{$comp}{'Name'}...\n");
}

# helper which does most of the work for uinstalling rpms for a component
# This function can be called within a components uninstall_X function
# uninstalls KernelRpms, FirmwareRpms, UserRpms and DebugRpms
# caller must handle any non-RPM files
sub uninstall_comp_rpms($$$$$)
{
	my $comp = shift();
	# the rpm command options
	my $option = shift();
	my $install_list = shift();
	my $uninstalling_list = shift();
	my $verbosity = shift();

	# try to uninstall meta pkg if it exists
	my $metapkg = "opameta_$comp";
	rpm_uninstall_matches($metapkg, $metapkg, '', "");

	rpm_uninstall_list2("any", "$option", $verbosity,
					 @{ $ComponentInfo{$comp}{'DebugRpms'}});
	rpm_uninstall_list2("any", "$option", $verbosity,
					 @{ $ComponentInfo{$comp}{'UserRpms'}});
	if (! $user_space_only ) {
		rpm_uninstall_list2("any", "$option", $verbosity,
					 @{ $ComponentInfo{$comp}{'FirmwareRpms'}});
		rpm_uninstall_list2("any", "$option", $verbosity,
					 @{ $ComponentInfo{$comp}{'KernelRpms'}});
	}
}

# build @AutostartComponents listing all components and subcomponents which
# have autostart capability.  They are listed in prefered startup order
sub build_autostart_components_list()
{
	my $comp;
	# only need to do once
	if (scalar(@AutostartComponents) != 0 ) {
		return;
	}
	foreach $comp ( @Components )
	{
		if ( $ComponentInfo{$comp}{'HasStart'} )
		{
			# StartComponents will list Components and SubComponents which
			# have start capability
			@AutostartComponents = ( @AutostartComponents, @{ $ComponentInfo{$comp}{'StartComponents'} })
		}
	}
}

# disable autostart for a list of components and
# all components dependent on given component
sub disable_components(@)
{
	my @disabled = ( @_ );
	my %need_disable = ();
	my %dont_need_disable = ();
	my $comp;

	build_autostart_components_list;
	foreach $comp ( @disabled ) {
		$need_disable{$comp} = 1;
		DebugPrint("disable $comp explicitly\n");
	}
	my $done = 0;
	while ( ! $done) {
		$done=1;
		foreach $comp ( @disabled ) {
			# comp will be disabled, any which depend on it as a
			# startprereqs will also be disabled
			foreach my $c ( @AutostartComponents ) {
				if (comp_has_startprereq_of($c, $comp)
					&& ! $need_disable{$c} && ! $dont_need_disable{$c} ) {
					if (comp_is_installed("$c") ) {
						@disabled = ( @disabled, $c );
						$need_disable{$c}=1;
						DebugPrint("also disable $c\n");
						$done=0;
					} else {
						$dont_need_disable{$c}=1;
						DebugPrint("no need to disable $c\n");
					}
				}
			}
		}
	}
	foreach $comp ( reverse(@AutostartComponents) ) {
		foreach my $c ( @disabled ) {
			if ( "$comp" eq "$c" ) {
				DebugPrint("invoke disable $c\n");
				comp_disable_autostart2($c,0);
			}
		}
	}
}

# enable autostart for a list of components and
# all components they depend on
sub enable_components(@)
{
	my @enabled = ( @_ );
	my %need_enable = ();
	my $comp;

	build_autostart_components_list;
	foreach $comp ( @enabled ) {
		$need_enable{$comp} = 1;
		DebugPrint("enable $comp explicitly\n");
	}
	my $done = 0;
	while ( ! $done) {
		$done=1;
		foreach $comp ( @enabled ) {
			# comp will be enabled, make sure all its
			# startprereqs will also be enabled
			foreach my $c ( @AutostartComponents ) {
				if (comp_has_startprereq_of($comp, $c) && ! $need_enable{$c} ) {
					DebugPrint("also enable $c\n");
					@enabled = ( $c, @enabled );
					$need_enable{$c}=1;
					$done=0;
				}
			}
		}
	}
	foreach $comp ( @AutostartComponents ) {
		foreach my $c ( @enabled ) {
			if ( "$comp" eq "$c" ) {
				DebugPrint("invoke enable $c\n");
				comp_enable_autostart2($c,0);
			}
		}
	}
}

# run build for all components
sub build_all_components($$$$)
{
	my $osver = shift();	# Kernel OS Version to build for
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a full rebuild

	my $comp;
	my $ret = 0;

	foreach $comp ( @Components )
	{
		my $rc = comp_build($comp,$osver,$debug,$build_temp,$force);
		if (0 != $rc) {
			NormalPrint "Unable to Build $ComponentInfo{$comp}{'Name'}\n";
		}
		$ret |= $rc;
	}
	return $ret;
}

sub count_hidden_comps()
{
	my $i;
	my $ret=0;

	for($i=0; $i < scalar(@Components); $i++)
	{
		my $comp = $Components[$i];
		if ($ComponentInfo{$comp}{'Hidden'}) {
			$ret++;
		}
	}
	return $ret;
}

# convert a screen selection into a Components subscript, accounting for Hidden
sub get_comp_subscript($$$)
{
	my $firstline=shift();
	my $maxlines=shift();
	my $selection=shift();
	my $index=0;
	my $i;

	for ($i=0; $i < scalar(@Components); $i++)
	{
		my $comp = $Components[$i];
		if ($index >= $firstline && $index < $firstline+$maxlines) {
			if (! $ComponentInfo{$comp}{'Hidden'}) {
				if ($index - $firstline == $selection) {
					return $i;
				}
				$index++;
			}
		} else {
			if (! $ComponentInfo{$comp}{'Hidden'}) {
				$index++;
			}
		}
	}
	return $i	# invalid entry return 1 past number of Components
}

sub show_install_menu($)
{
	my $showversion = shift();	# should per comp versions be shown

	my $inp;
	my %available = ();
	my %installed = ();
	my %installed_version = ();
	my %media_version = ();
	my %isupgrade = ();
	my %installState = ();
	my %statusMessage = ();
	my %boldMessage = ();
	my $comp;
	my $i;
	my $newstate = $State_Uninstall;	# most recent state change for a comp
	my $firstline = 0;
	my $maxlines=14;
	my $num_hidden_comps = count_hidden_comps();

	print "Determining what is installed on system...\n";
	DumpComponents(1);
	foreach $comp ( @Components )
	{
		$available{$comp} = comp_is_available("$comp");
		$installed{$comp} = comp_is_installed("$comp");
		if ( $available{$comp} ) {
			$media_version{$comp} = comp_media_version($comp);
		} else {
			$media_version{$comp} = "";
		}
		if ( $installed{$comp} ) {
			$installed_version{$comp} = comp_installed_version($comp);
			$isupgrade{$comp}= ($installed_version{$comp} ne $media_version{$comp});
		} else {
			$installed_version{$comp} = "";
			$isupgrade{$comp}=1;
		}
		$installState{$comp}= setstate($installed{$comp}, $available{$comp},
							$isupgrade{$comp}, $ComponentInfo{$comp}{'DefaultInstall'});
	}
	# to avoid a subtle effect, mark as not available any items whose
	# coreqs are not available.  Such packagings should not
	# occur, but better to be safe
	foreach $comp ( @Components )
	{
		if (! $available{$comp}) {
			foreach my $c ( @Components )
			{
				if (comp_has_coreq_of($c, $comp) && $available{$c}) {
					$available{$c}=0;
				}
			}
		}
	}

	do {{
		if ( $Default_Install) {
			# setstate set UnInstall or DoNotInstall for those not available
			# force install for all available even if UpToDate
			# or ComponentInfo{comp}{'DefaultInstall'} is DoNotInstall
			foreach $comp ( @Components )
			{
				if ( $available{$comp}
					&& ($installState{$comp} != $State_DoNotInstall
						|| $ComponentInfo{$comp}{'DefaultInstall'} != $State_DoNotAutoInstall)) {
					$installState{$comp} = $State_Install;
				}
			}
			$newstate = $State_Install;
			$inp='P';
		} elsif ( $Default_Upgrade) {
			foreach $comp ( @Components )
			{
				if ( $installed{$comp} )
				{
					if ( $available{$comp} )
					{
						$installState{$comp} = $State_Install;
					} elsif ( ! $isupgrade{$comp} ) {
						$installState{$comp} = $State_UpToDate;
					} else {
						$installState{$comp} = $State_Uninstall; # we must uninstall
					}
				} else {
					$installState{$comp} = $State_DoNotInstall;
				}
			}
			$newstate = $State_Install;
			$inp='P';
		} elsif ( $Default_CompInstall) {
			foreach $comp ( @Components )
			{
				if ( $Default_Components{$comp} )
				{
					if ( $available{$comp} )
					{
						$installState{$comp} = $State_Install;
					} else {
						NormalPrint "Unable to install $ComponentInfo{$comp}{'Name'}, Not Available\n";
						# setstate provided a reasonable default action
					}
				} else {
					# setstate defaulted to install all available and not installed
					# for version updates re-install to be safe
					if ( $installState{$comp} == $State_Install
						&& ( ! $installed{$comp} || ! $isupgrade{$comp} ) )
					{
						# Do Not Install
						$installState{$comp} = $State_DoNotInstall;
					}
				}
			}
			$newstate = $State_Install;
			$inp='P';
		} else {
			system "clear";
			printf ("$BRAND OPA Install ($VERSION $DBG_FREE) Menu\n\n");
			my $screens = int((scalar(@Components) - $num_hidden_comps + $maxlines-1)/$maxlines);

			if($GPU_Install == 1) {
				printf ("Install GPU Direct components, ensure nvidia drivers + SDK are present \n\n");
			}
			if ($screens > 1 ) {
				printf ("Please Select Install Action (screen %d of $screens):\n",
							$firstline/$maxlines+1);
			} else {
				printf ("Please Select Install Action:\n");
			}
			my $index=0;
			for ($i=0; $i < scalar(@Components); $i++)
			{
				$comp = $Components[$i];
				if ($index >= $firstline && $index < $firstline+$maxlines) {
					if ($showversion && "$statusMessage{$comp}" eq "") {
						if ($available{$comp}) {
							$statusMessage{$comp} = $media_version{$comp};
							$boldMessage{$comp} = 0;
						} elsif($installed{$comp}) {
							$statusMessage{$comp} = $installed_version{$comp};
							$boldMessage{$comp} = 0;
						}
					}
					if (! $ComponentInfo{$comp}{'Hidden'}) {
						printf ("%x) %-20s", $index-$firstline, $ComponentInfo{$comp}{'Name'});
						printInstallAvailableState($installed{$comp},
										$available{$comp},
										$isupgrade{$comp},
										$installState{$comp},
										$boldMessage{$comp}, $statusMessage{$comp});
						$index++;
					}
				} elsif (! $ComponentInfo{$comp}{'Hidden'}) {
					$index++;
				}
			}

			printf ("\n");
			if ($screens > 1 ) {
				printf ("N) Next Screen\n");
			}
			printf (  "P) Perform the selected actions       I) Install All\n");
			printf (  "R) Re-Install All                     U) Uninstall All\n");
			printf (  "X) Return to Previous Menu (or ESC)\n");	

			$inp = getch();

			if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC )
			{
				return;
			}

			# do not clear status messages when jump between screens
			if ($inp !~ /[nN]/ ) {
				%statusMessage = ();
				%boldMessage = ();
			}
		}

		if ($inp =~ /[nN]/ )
		{
			if (scalar(@Components) > $maxlines) {
				$firstline += $maxlines;
				if ($firstline >= scalar(@Components)) {
					$firstline=0;
				}
			}
		} elsif ($inp =~ /[rR]/ )
		{
			foreach $comp ( @Components )
			{
				if ( $installed{$comp} && $available{$comp}) {
					$installState{$comp} = $State_Install;
				}
			}
		} elsif ($inp =~ /[iI]/ )
		{
			foreach $comp ( @Components )
			{
				if ( $available{$comp} ) {
					$installState{$comp} = $State_Install;
				}
			}
			$newstate = $State_Install;
		} elsif ($inp =~ /[uU]/ )
		{
			foreach $comp ( @Components )
			{
				$installState{$comp} = $State_Uninstall;
			}
			$newstate = $State_Uninstall;
		} elsif ($inp =~ /[0123456789abcdefABCDEF]/) {
			my $value = hex($inp);
			my $index = get_comp_subscript($firstline, $maxlines, $value);
			if ( $value < $maxlines && $index < scalar(@Components)) {
				my $selected = $Components[$index];
				$installState{$selected} = shiftstate($installState{$selected},$installed{$selected},$available{$selected},$isupgrade{$selected});
				$newstate = $installState{$selected};
			}
		}

		if (! will_be_on_system($newstate)) {
			# something is being uninstalled or not installed
			# loop through a few times to catch all coreqs, prereqs
			# and coreqs of prereqs
			my $done = 0;	# we are done if we loop through with no changes
			while (! $done) {
				$done=1;
				foreach $comp ( @Components )
				{
					if (! will_be_on_system($installState{$comp})) {
						# comp will not be on system, make sure all its
						# pre/coreqs will also not be on system
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($c, $comp)
								&& will_be_on_system($installState{$c})) {
								$statusMessage{$c}="requires $ComponentInfo{$comp}{'Name'}";
								$boldMessage{$c}=1;
								$installState{$c}=$installed{$c}?$State_Uninstall:$State_DoNotInstall;
								$done=0;
							}
						}
					}
					if ($ComponentInfo{$comp}{'Hidden'}) {
						# if no longer needed, also remove it
						my $needed = 0;	# is $comp needed
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($c, $comp)
								&& will_be_on_system($installState{$c})) {
								$needed=1;
							}
						}
						if (! $needed && will_be_on_system($installState{$comp})) {
							$installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall;
							$done=0;
						}
					}
				}
			}
		} elsif (will_be_on_system($newstate)) {
			# something is being installed or left on system
			# loop through a few times to catch all coreqs, prereqs
			# and coreqs of prereqs
			my $done = 0;	# we are done if we loop through with no changes
			my $forcedone = 0;	# used to break infinite loop in subtle issue below
			while (! $forcedone && ! $done) {
				$done=1;
				foreach $comp ( @Components )
				{
					if (will_be_on_system($installState{$comp})) {
						# comp will be on system, make sure all its
						# pre/coreqs will also be on system
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($comp, $c)
								&& ! will_be_on_system($installState{$c})) {
								if (! $available{$c} ) {
									# pre/coreq $c not available, can't install comp
									$statusMessage{$comp}="requires $ComponentInfo{$c}{'Name'}";
									$boldMessage{$comp}=1;
									$installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall;
									# this should not occur for coreqs
									# however there are subtle effects here.
									# If we install an item which has a prereq
									# whose prereq is not available we could get
									# stuck with an invalid combination since we
									# will have marked the 1st prereq installed,
									# found the 2nd prereq problem
									# unmarked the 1st prereq but still have
									# left the original item to be installed
									# bail to avoid infinite loop
									$forcedone=1;
									last;
								} else {
									# also install $c
									$statusMessage{$c}="needed by $ComponentInfo{$comp}{'Name'}";
									$boldMessage{$c}=1;
									$installState{$c}=$State_Install;
								}
								$done=0;
							}
						}
					}
					if ($ComponentInfo{$comp}{'Hidden'} && $available{$comp}
						&& will_be_on_system($installState{$comp})) {
						# if all prereqs being reinstalled also reinstall it
						my $reinstall = 1;	# no already installed dependents
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($c, $comp)
								&& will_be_on_system($installState{$c})
								&& $installState{$c} != $State_Install) {
								$reinstall=0;
							}
						}
						if ($reinstall) {
							$installState{$comp}=$State_Install;
							# no need to force another loop, didn't change
							# will_be_on_system($comp)
						}
					}
				}
			}
		}

		if ($inp =~ /[pP]/) {
			# perform the install
			my $updateFirmware=0;

			# build a list of what will be installed after installation completes
			# use a space separate string so easier to pass and can be "grep'ed"
			my $install_list = "";
			my $installing_list = "";
			my $uninstalling_list = "";
			my $have_some_uptodate = 0;
			foreach $comp ( @Components )
			{
				if ($installState{$comp} == $State_UpToDate) {
					$have_some_uptodate = 1;
				}
				if ($installState{$comp} == $State_Install
					|| $installState{$comp} == $State_UpToDate) {
					$install_list .= " $comp ";
				}
				if ($installState{$comp} == $State_Install) {
					$installing_list .= " $comp ";
				}
				if ($installState{$comp} == $State_Uninstall) {
					$uninstalling_list .= " $comp ";
				}
			}

			# remove any alias pkgs if it exists. Meta pkgs will be handled in comp uninstall.
			rpm_uninstall_matches("opanode_", "opanode_", "", "");

			# first uninstall what will be removed, do this in reverse order
			# so dependency issues are avoided
			foreach $comp ( reverse(@Components) ) {
				if ($installState{$comp} == $State_Uninstall) {
					comp_uninstall($comp, $install_list, $uninstalling_list);
					$installed{$comp} = 0;
				}
			}
			if ( "$WrapperComponent" ne "" && "$installing_list" eq "" && "$install_list" eq "" ) {
				comp_uninstall($WrapperComponent, $install_list, $uninstalling_list);
			}

			if ($have_some_uptodate ) {
				# determine if some up to date components need to be reinstalled
				# for example due to a change in install prefix, install options ...
				# to determine this run need_reinstall for all components which
				# will be installed or are up to date.  Net result is we may change
				# some or all components in State_UpToDate to State_Install

				my $need_reinstall_all = 0;
				my $need_reinstall_some = 0;
				foreach $comp ( @Components )
				{
					if (($installState{$comp} == $State_Install
							|| $installState{$comp} == $State_UpToDate)
						&& $available{$comp} ) {
						my $reins = comp_need_reinstall($comp,$install_list,$installing_list);
						if ("$reins" eq "all") {
							VerbosePrint("$comp needs reinstall all\n");
							$need_reinstall_all = 1;
							last;
						} elsif ("$reins" eq "this") {
							if ($installState{$comp} == $State_UpToDate
								&& $available{$comp} ) {
								VerbosePrint("$comp needs reinstall\n");
								$installState{$comp} = $State_Install;
								$need_reinstall_some = 1;
							}
						}
					}
				}
				if ($need_reinstall_all || $need_reinstall_some) {
					if ($need_reinstall_all) {
						NormalPrint "INSTALL options require Reinstall of all UpToDate Components\n";
					} else {
						NormalPrint "Reinstall of some UpToDate Components is Required\n";
					}
					$installing_list  = "";	# recompute
					foreach $comp ( @Components )
					{
						if ($need_reinstall_all
							&& $installState{$comp} == $State_UpToDate
							&& $available{$comp} ) {
							$installState{$comp} = $State_Install;
						}
						if ($installState{$comp} == $State_Install) {
							$installing_list .= " $comp ";
						}
					}
				}
			}
			# check OS pre-reqs for all components which will be installed
			my $have_all_os_prereqs=1;
			foreach $comp ( @Components )
			{
				if ($installState{$comp} == $State_Install) {
					if (0 != comp_check_os_prereqs($comp)) {
						$have_all_os_prereqs=0;
						NormalPrint "Lacking OS Prereqs for $ComponentInfo{$comp}{'Name'}\n";
					}
				}
			}
			if (! $have_all_os_prereqs) {
				HitKeyCont;
				last;
			}

			# run pre-install for all components which will be installed
			# Reverse the order to avoid dependency issues
			foreach $comp ( reverse(@Components) )
			{
				if ($installState{$comp} == $State_Install) {
					if (0 != comp_preinstall($comp,$install_list,$installing_list)) {
						NormalPrint "Unable to Prepare $ComponentInfo{$comp}{'Name'} for Install\n";
						HitKeyCont;
						last;
					}
				}
			}

			# Now install components
			if ( "$WrapperComponent" ne "" && "$installing_list" ne "" ) {
				comp_install($WrapperComponent, $install_list, $installing_list);
			}
			foreach $comp ( @Components )
			{
				if ($installState{$comp} == $State_Install) {
					comp_install($comp, $install_list, $installing_list);
					if ( $ComponentInfo{$comp}{'HasFirmware'} ) {
						$updateFirmware=1;
					}
				}
			}

			# run post-install for all components which were installed
			foreach $comp ( @Components )
			{
				if ($installState{$comp} == $State_Install) {
					comp_postinstall($comp, $install_list, $installing_list);
				}
			}

			%installed = ();
			if ( $Default_Prompt ) {
				foreach $comp ( @Components )
				{
					$installed{$comp} = 0;
				}
				# limit autostart to newly installed components with a
				# default start.  Also include their start prereqs.
				# Note start prereqs are all inclusive, so we don't need to
				# find prereqs of prereqs
				foreach $comp ( @Components )
				{
					if ($installState{$comp} == $State_Install
						&& $ComponentInfo{$comp}{'HasStart'}
						&& ($Default_SameAutostart
							|| $ComponentInfo{$comp}{'DefaultStart'}) ) {
						$installed{$comp} = 1;
						foreach my $c ( @Components ) {
							if (comp_has_startprereq_of($comp, $c)) {
								$installed{$c} = 1;
							}
						}
					}
				}
			} else {
				foreach $comp ( @Components )
				{
					if ($installState{$comp} == $State_Install
						|| $installState{$comp} == $State_UpToDate) {
						$installed{$comp} = 1;
					} else {
						$installed{$comp} = 0;
					}
				}
			}
			show_autostart_menu(0);

			# show_autostart_menu unconditionally requested user hit return,
			# update_hca_firmware will also as needed, so only request return below
			# if one of these functions does something.
			my $need_ret = 0;
			$need_ret |= check_depmod;
			$need_ret |= check_ldconfig;
			$need_ret |= check_need_reboot;
			if ($need_ret) {
				HitKeyCont;
			}
			return;
		}
	}} until ($Default_Prompt);
	# we had an error above
	$exit_code = 1;
}

sub show_installed($)
{
	my $showversion = shift();	# should per comp versions be shown

	my %installed = ();
	my %statusMessage = ();
	my $comp;
	my $i;

	system "clear";
	printf ("$BRAND OPA Installed Software ($VERSION)\n\n");
	my $index=0;
	for ($i=0; $i < scalar(@Components); $i++)
	{
		if ($index > 0 && ($index % 20 == 0) ) {
			HitKeyCont;
		}
		$comp = $Components[$i];
		$installed{$comp} = comp_is_installed("$comp");
		if ( $showversion && $installed{$comp} ) {
			$statusMessage{$comp} = comp_installed_version($comp);
		}
		if (! $ComponentInfo{$comp}{'Hidden'}) {
			printf ("   %-20s ", $ComponentInfo{$comp}{'Name'});
			printInstallState($installed{$comp}, 0, 0, "$statusMessage{$comp}");
			$index++;
		}
	}
	HitKeyCont;
}

sub show_uninstall_menu($)
{
	my $showversion = shift();	# should per comp versions be shown

	my %installed = ();
	my %installed_version = ();
	my %installState = ();
	my %statusMessage = ();
	my %boldMessage = ();
	my $inp;
	my $comp;
	my $i;
	my $newstate;	# most recent state change for a comp
	my $firstline = 0;
	my $maxlines=14;
	my $num_hidden_comps = count_hidden_comps();

	print "Determining what is installed on system...\n";
	DumpComponents(0);
	foreach $comp ( @Components )
	{
		$installed{$comp} = comp_is_installed("$comp");
		if ($installed{$comp}) {
			$installed_version{$comp} = comp_installed_version("$comp");
		}
		$installState{$comp}= setstate($installed{$comp},0,0,$State_DoNotInstall);
	}
	do {
		if ( $Default_Uninstall) {
			foreach $comp ( @Components )
			{
				$installState{$comp} = $State_Uninstall;
			}
			$newstate = $State_Uninstall;
			$inp="P";
		} elsif ( $Default_CompUninstall) {
			foreach $comp ( @Components )
			{
				if ( $Default_Components{$comp} )
				{
					$installState{$comp} = $State_Uninstall;
				}
			}
			$newstate = $State_Uninstall;
			$inp="P";
		} else {
			system "clear";
			printf ("$BRAND OPA Uninstall Menu ($VERSION)\n\n");
			my $screens = int((scalar(@Components)-$num_hidden_comps + $maxlines-1)/$maxlines);
			if ($screens > 1 ) {
				printf ("Please Select Uninstall Action (screen %d of $screens):\n",
							$firstline/$maxlines+1);
			} else {
				printf ("Please Select Uninstall Action:\n");
			}
			my $index=0;
			for($i=0; $i < scalar(@Components); $i++)
			{
				$comp = $Components[$i];
				if ($index >= $firstline && $index < $firstline+$maxlines) {
					if ($showversion && "$statusMessage{$comp}" eq ""
						&& $installed{$comp}) {
						$statusMessage{$comp} = $installed_version{$comp};
						$boldMessage{$comp} = 0;
					}
					if (! $ComponentInfo{$comp}{'Hidden'}) {
						printf ("%x) %-20s ", $index-$firstline, $ComponentInfo{$comp}{'Name'});
						printInstallState($installed{$comp}, ($installState{$comp} == $State_Uninstall),
							$boldMessage{$comp}, $statusMessage{$comp});
						$index++;
					}
				} elsif (! $ComponentInfo{$comp}{'Hidden'}) {
					$index++;
				}
			}

			printf ("\n");
			if ($screens > 1 ) {
				printf ("N) Next Screen\n");
			}
			printf (  "P) Perform the selected actions\n");
			printf (  "U) Uninstall All\n");
			printf (  "X) Return to Previous Menu (or ESC)\n");
				

			$inp = getch();
		
			if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC)
			{
				return;
			}

			# do not clear status messages when jump between screens
			if ($inp !~ /[nN]/ )
			{
				%statusMessage = ();
				%boldMessage = ();
			}
		}

		if ($inp =~ /[nN]/ )
		{
			if (scalar(@Components) > $maxlines) {
				$firstline += $maxlines;
				if ($firstline >= scalar(@Components)) {
					$firstline=0;
				}
			}
		} elsif ($inp =~ /[uU]/ )
		{
			foreach $comp ( @Components )
			{
				$installState{$comp} = $State_Uninstall;
			}
			$newstate = $State_Uninstall;
		}
		elsif ($inp =~ /[0123456789abcdefABCDEF]/)
		{
			my $value = hex($inp);
			my $index = get_comp_subscript($firstline, $maxlines, $value);
			if ( $value < $maxlines && $index < scalar(@Components)) {
				my $selected = $Components[$index];
				$installState{$selected} = shiftstate($installState{$selected},$installed{$selected},0,0);
				$newstate = $installState{$selected};
			}
		}

		if (! will_be_on_system($newstate)) {
			my $done = 0;	# we are done if we loop through with no changes
			# something is being uninstalled or not installed
			# loop through a few times to catch all coreqs, prereqs
			# and coreqs of prereqs
			while (! $done) {
				$done=1;
				foreach $comp ( @Components )
				{
					if (! will_be_on_system($installState{$comp})) {
						# comp will not be on system, make sure all its
						# pre/coreqs will also not be on system
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($c, $comp)
								&& will_be_on_system($installState{$c})) {
								$statusMessage{$c}="requires $ComponentInfo{$comp}{'Name'}";
								$boldMessage{$c}=1;
								$installState{$c}=$installed{$c}?$State_Uninstall:$State_DoNotInstall;
								$done=0;
							}
						}
					}
					if ($ComponentInfo{$comp}{'Hidden'}) {
						# if no longer needed, also remove it
						my $needed = 0;	# is $comp needed
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($c, $comp)
								&& will_be_on_system($installState{$c})) {
								$needed=1;
							}
						}
						if (! $needed && will_be_on_system($installState{$comp})) {
							$installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall;
							$done=0;
						}
					}
				}
			}
		} elsif (will_be_on_system($newstate)) {
			# something is being left on system
			# loop through a few times to catch all coreqs, prereqs
			# and coreqs of prereqs
			my $done = 0;	# we are done if we loop through with no changes
			my $forcedone = 0;	# used to force infinite loop in subtle issue below
			while (! $forcedone && ! $done) {
				$done=1;
				foreach $comp ( @Components )
				{
					if (will_be_on_system($installState{$comp})) {
						# comp will be on system, make sure all its
						# pre/coreqs will also be on system
						foreach my $c ( @Components )
						{
							if (comp_has_req_of($comp, $c)
								&& ! will_be_on_system($installState{$c})) {
								if (! $installed{$c} ) {
									# pre/coreq $c not installed, can't keep comp
									# this is not expected to occur, but is
									# a safety net for corrupted systems
									$statusMessage{$comp}="requires $ComponentInfo{$c}{'Name'}";
									$boldMessage{$comp}=1;
									$installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall;
									# bail to avoid infinite loop, especially
									# for prereq chains and missing coreqs
									# see install_menu discussion for a similar
									# related issue
									$forcedone=1;
									last;
								} else {
									# also install $c
									$statusMessage{$c}="needed by $ComponentInfo{$comp}{'Name'}";
									$boldMessage{$c}=1;
									$installState{$c}=$State_Install;
								}
								$done=0;
							}
						}
					}
				}
			}
		}

		if ($inp =~ /[pP]/)
		{
			# build a list of what will be installed after installation completes
			# use a space separate string so easier to pass and can be "grep'ed"
			my $install_list = "";
			my $uninstalling_list = "";
			foreach $comp ( @Components )
			{
				if ($installState{$comp} == $State_Install
					|| $installState{$comp} == $State_UpToDate) {
					$install_list .= " $comp ";
				}
				if ($installState{$comp} == $State_Uninstall) {
					$uninstalling_list .= " $comp ";
				}
			}

			# remove any alias pkgs if it exists. Meta pkgs will be handled in comp uninstall.
			rpm_uninstall_matches("opanode_", "opanode_", "", "");

			# perform the uninstall, work backwards through list
			foreach $comp ( reverse(@Components) )
			{
				if ($installState{$comp} == $State_Uninstall)
				{
					comp_uninstall($comp, $install_list, $uninstalling_list);
					$installed{$comp} = 0;
				}
			}
			if ( "$WrapperComponent" ne "" && "$install_list" eq "" ) {
				comp_uninstall($WrapperComponent, $install_list, $uninstalling_list);
			}
			# since we did an uninstall should request a return
			my $need_ret = 1;
			$need_ret |= check_depmod;
			$need_ret |= check_ldconfig;
			$need_ret |= check_need_reboot;
			if ($need_ret) {
				HitKeyCont;
			}
			return;
		}
	}while( !$Default_Prompt )
}

sub reconfig_autostart()
{
	my %installed = ();
	my $comp;

	build_autostart_components_list;
	foreach $comp ( @Components ) {
		$installed{$comp} = comp_is_installed("$comp");
		DebugPrint("installed($comp)=$installed{$comp}\n");
		# fill in subcomponents to simplify tests for Default_*Components below
		# if show_autostart_menu is called, it will ignore these extra entries
		foreach my $c ( @{ $ComponentInfo{$comp}{'StartComponents'} }) {
			$installed{$c} = $installed{$comp};
		}
	}
	if (! $Default_Autostart) {
		# interactive menu, use previous value as default
		show_autostart_menu(1);
	} else {
		if ( $Default_DisableAutostart) {
			# build list of components/subcomponents to disable
			my @disabled = ();
			foreach $comp ( @AutostartComponents ) {
				if ( $installed{$comp} ) {
					if ($Default_DisabledComponents{$comp}) {
						@disabled = ( @disabled, $comp );
					}
				}
			}
			disable_components(@disabled);
		}
		if ( $Default_EnableAutostart) {
			# build list of components/subcomponents to enable
			my @enabled = ();
			foreach $comp ( @AutostartComponents ) {
				if ( $installed{$comp} ) {
					if ($Default_EnabledComponents{$comp}) {
						@enabled = ( @enabled, $comp );
					}
				} else {
				}
			}
			enable_components(@enabled);
		}
		if (! $Default_DisableAutostart && ! $Default_EnableAutostart) {
			# use component specific default as value
			show_autostart_menu(2);
		}
	}
}

# states:
# $Start_Start - Enable Autostart
# $Start_NoStart - Disable Autostart
sub printStartState($$$$)
{
	my $enabled     = shift();
	my $boldmessage = shift();
	my $message   = shift();
	my $state_change = shift();

	if ( $enabled )
	{
		print GREEN, "[Enable ]", RESET;
	} else {
		print RED, "[Disable]", RESET;
	}
	if ( $state_change )
	{
		print " *";
	} else {
		print "  ";
	}
	if ("$message" ne "" && $boldmessage) {
		print BOLD, RED "$message", RESET, "\n";
	} else {
		print "$message\n";
	}

	return;
}

# convert a screen selection into a Autostart subscript
sub get_subscript($$$@)
{
	my $firstline=shift();
	my $maxlines=shift();
	my $selection=shift();
	my @list = ( @_ );
	my $index=0;
	my $i;

	for ($i=0; $i < scalar(@list); $i++)
	{
		my $comp = $list[$i];
		if ($index >= $firstline && $index < $firstline+$maxlines) {
			if ($index - $firstline == $selection) {
				return $i;
			}
			$index++;
		} else {
			$index++;
		}
	}
	return $i	# invalid entry return 1 past number of Components
}
sub show_autostart_menu($)
{
	my $sel_mode = shift(); # possible values are: 1: keep previous, 0: use default, 2: enable

	my $inp;
	my @PromptAutostart = ();
	my %enabled = ();
	my %statusMessage = ();
	my %boldMessage = ();
	my $comp;
	my $i;
	my $newenabled = 0;	# most recent state change for a comp
	my $firstline = 0;
	my $maxlines=13;

	# figure out which to prompt for
	# while selections may include SubComponents, we only look
	# at components and include all their subcomponents in the prompts
	foreach $comp ( @Components )
	{
		if ( comp_is_installed("$comp") && $ComponentInfo{$comp}{'HasStart'} )
		{
			# StartComponents will list Components and SubComponents which
			# have start capability
			@PromptAutostart = ( @PromptAutostart, @{ $ComponentInfo{$comp}{'StartComponents'} })
		}
	}
	if ( $Default_SameAutostart ) {
		foreach $comp ( @PromptAutostart )
		{
			my $state;
			# we recreate startup files to ensure they are in the
			# startup order of the new release
			if ( comp_IsAutostart2($comp) == 1 )
			{
				comp_enable_autostart2($comp,1);
				$state = "enabled";
			} else {
				comp_disable_autostart2($comp,1);
				$state = "disabled";
			}
			my $desc = comp_autostart_desc($comp);
			NormalPrint "Leaving autostart for $desc at its previous value: $state\n";
		}
		return;
	}

	foreach $comp ( @PromptAutostart )
	{
		DebugPrint("prompt for $comp\n");
		if ($sel_mode == 1) {
			# keep previous
			$enabled{$comp} = comp_IsAutostart2($comp);
		} elsif ($sel_mode == 2) {
			# enable
			$enabled{$comp} = 1;
		} else {
			# use default
			$enabled{$comp} = $ComponentInfo{$comp}{'DefaultStart'};
		}
	}
	while() {
		if ( $Default_Prompt) {
			$inp='P';
		} else {
			system "clear";        
			printf ("$BRAND OPA Autostart ($VERSION $DBG_FREE) Menu\n\n");
			my $screens = int((scalar(@PromptAutostart) + $maxlines-1)/$maxlines);
			if ($screens > 1 ) {
				printf ("Please Select Autostart Option (screen %d of $screens):\n",
							$firstline/$maxlines+1);
			} else {
				printf ("Please Select Autostart Option:\n");
			}
			my $index=0;
			for ($i=0; $i < scalar(@PromptAutostart); $i++)
			{
				$comp = $PromptAutostart[$i];
				my $state_change = 0;
				if( comp_IsAutostart2($comp) != $enabled{$comp} )
				{
					$state_change = 1;
				}
				if ($index >= $firstline && $index < $firstline+$maxlines) {
					printf ("%x) %-32s", $index-$firstline, comp_autostart_desc($comp));
					printStartState($enabled{$comp},
									$boldMessage{$comp}, $statusMessage{$comp}, $state_change);
					$index++;
				} else {
					$index++;
				}
			}
			printf("\n*: new desired state\n");
			printf ("\n");
			if ($screens > 1 ) {
				printf ("N) Next Screen\n");
			}
			printf (  "P) Perform the autostart changes\n");
			printf (  "S) Autostart All                     R) Autostart None\n");
			printf (  "X) Return to Previous Menu (or ESC)\n");	

			$inp = getch();                
			
			if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC ) 
			{
				return;
			}

			# do not clear status messages when jump between screens
			if ($inp !~ /[nN]/ ) {
				%statusMessage = ();
				%boldMessage = ();
			}

		}

		if ($inp =~ /[nN]/ )
		{
			if (scalar(@PromptAutostart) > $maxlines) {
				$firstline += $maxlines;
				if ($firstline >= scalar(@PromptAutostart)) {
					$firstline=0;
				}
			}
		} elsif ($inp =~ /[sS]/ )
		{
			foreach $comp ( @PromptAutostart )
			{
				$enabled{$comp} = 1;
			}
			$newenabled = 1;
		} elsif ($inp =~ /[rR]/ )
		{
			foreach $comp ( @PromptAutostart )
			{
				$enabled{$comp} = 0;
			}
			$newenabled = 0;
		} elsif ($inp =~ /[0123456789abcdefABCDEF]/) {
			my $value = hex($inp);
			my $index = get_subscript($firstline, $maxlines, $value, @PromptAutostart);
			if ( $value < $maxlines && $index < scalar(@PromptAutostart)) {
				my $selected = $PromptAutostart[$index];
				$enabled{$selected} = ! $enabled{$selected};
				$newenabled = $enabled{$selected};
			}
		}

		if (! $newenabled) {
			# something is being disabled
			# loop through a few times to catch all prereqs
			# and prereqs of prereqs
			my $done = 0;	# we are done if we loop through with no changes
			while (! $done) {
				$done=1;
				foreach $comp ( @PromptAutostart )
				{
					if (! $enabled{$comp}) {
						# comp will be disabled, make sure all its
						# startprereqs will also be disabled
						foreach my $c ( @PromptAutostart )
						{
							if (comp_has_startprereq_of($c, $comp) && $enabled{$c}) {
								$statusMessage{$c}="requires $ComponentInfo{$comp}{'Name'}";
								$boldMessage{$c}=1;
								$enabled{$c}=0;
								$done=0;
							}
						}
					}
				}
			}
		} else {
			# something is being disabled
			# loop through a few times to catch all prereqs
			my $done = 0;	# we are done if we loop through with no changes
			while (! $done) {
				$done=1;
				foreach $comp ( @PromptAutostart )
				{
					if ($enabled{$comp}) {
						# comp will be enabled, make sure all its
						# startprereqs will also be enabled
						foreach my $c ( @PromptAutostart )
						{
							if (comp_has_startprereq_of($comp, $c) && ! $enabled{$c}) {
								# also enable $c
								$statusMessage{$c}="needed by $ComponentInfo{$comp}{'Name'}";
								$boldMessage{$c}=1;
								$enabled{$c}=1;
								$done=0;
							}
						}
					}
				}
			}
		}

		if ($inp =~ /[pP]/) {
			# perform the changes

			# first disable, do this in reverse order
			# so dependency issues are avoided
			foreach $comp ( reverse(@PromptAutostart) ) {
				if (! $enabled{$comp}) {
					comp_disable_autostart2($comp,0);
				}
			}
			# now enable
			foreach $comp ( @PromptAutostart ) {
				if ($enabled{$comp}) {
					comp_enable_autostart2($comp,0);
				}
			}
			HitKeyCont;
			return;
		}
		if ( $Default_Prompt ) {
			return;
		}
	}
		$exit_code = 1;	# unexpected
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# =============================================================================
# The functions and constants below assist in editing hotplug and blacklists
# to prevent autoloading of drivers prior to startup scripts

my $HOTPLUG_HARDWARE_DIR = "/etc/sysconfig/hardware";

# if not existing file on OS, use this location and create empty file
# code in add_blacklist depends on pre-existance of file
my $HOTPLUG_BLACKLIST_FILE = "/etc/modprobe.d/opa-blacklist.conf";
my $HOTPLUG_BLACKLIST_PREFIX = "blacklist";
my $HOTPLUG_BLACKLIST_SPACE = " ";
my $HOTPLUG_BLACKLIST_SPACE_WILDCARD = "[ 	]*";

# check if the module is blacklisted
sub is_blacklisted($)
{
	my $module = shift();

	my $file = "${HOTPLUG_BLACKLIST_FILE}";
	my $found;

	if (! -f "$file")
	{
		return 0;
	}

	return ! system("grep -q $module $file");
}

# add to list to prevent automatic hotplug of driver
sub add_blacklist($)
{
	my $module = shift();

	my $file = "${HOTPLUG_BLACKLIST_FILE}";
	my $found;

	if (! -e "$file")
	{
		system("touch $file"); # Blacklist file missing, let's create it.
	} elsif (! -f "$file") {
		return; # Blacklist file exists but is not regular file, abort.
	}
	open (INPUT, "$file");
	open (OUTPUT, ">>$TMP_CONF");

	select (OUTPUT);
	while (($_=<INPUT>))
	{
		if (/^${HOTPLUG_BLACKLIST_PREFIX}${HOTPLUG_BLACKLIST_SPACE_WILDCARD}$module[ 	]*$/)
		{
			$found++;
		} 
		print $_;
	}
	if (!defined($found))
	{
		print "${HOTPLUG_BLACKLIST_PREFIX}${HOTPLUG_BLACKLIST_SPACE}$module\n";
	}
	select(STDOUT);

	close (INPUT);
	close (OUTPUT);
	system "mv $TMP_CONF $file";

	# also remove any hotplug config files which load the driver
	open hwconfig, "ls /$HOTPLUG_HARDWARE_DIR/hwcfg* 2>/dev/null |"
			|| Abort "Unable to open pipe\n";
	while (<hwconfig>) {
		chop;
		if ( ! system("grep -q \"MODULE.*'$module'\" $_ 2>/dev/null") ) {
			system "rm -f $_"
		}
	}
	close hwconfig;
}

sub remove_blacklist($)
{
	my($module) = shift();

	my($file) = "${HOTPLUG_BLACKLIST_FILE}";
	if (! -f "$file")
	{
		return;
	}
	open (INPUT, "$file");
	open (OUTPUT, ">>$TMP_CONF");

	select (OUTPUT);
	while (($_=<INPUT>))
	{
		if (/^${HOTPLUG_BLACKLIST_PREFIX}${HOTPLUG_BLACKLIST_SPACE_WILDCARD}$module[ 	]*$/)
		{
			next;
		} else {
			print $_;
		}
	}
	select(STDOUT);

	close (INPUT);
	close (OUTPUT);
	system "mv $TMP_CONF $file";
	if ( -z "$file" ) {
	   system("rm -f $file"); # blacklist file is empty, remove it.
	}
}

#!/usr/bin/perl
## BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]

#

use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ==========================================================================
# IP address configuration
# used for IPoIB at present but generalized so could support VNIC or
# iPathEther also

my $FirstIPoIBInterface=0; # first device is ib0
my $MAX_HFI_PORTS=20;	# maximum valid ports

# Validate the passed in IP address (or netmask).
# Verify there are enough dots '.' and same number of
# decimal numbers. This is not comprehensive.
#
# inputs:
#	IP address in dot notation.  eg:
#	'a.b.c.d' or 'a.b.c' or 'a.b'
#
# outputs:
#	0 == failure(not a valid IP address)
#	1 == Success.

sub Validate_IP_Addr($)
{
	$_ = shift();		# setup for translate & other cmds

	my($count)= 0;

	# verify there are 3 and only 3 dots, 'a.b.c.d'.
	# translate '.' to self, side-effect is the count.

	$count=(tr/\.//);
	if ( $count < 1 || $count > 3 )
	{
		return 0;
	}

	# accept only decimal digits separated by dots.
	if ( /[0-9\.]/ ) 
	{
		# because we checked dots above, any of the three below is ok
		if ( /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ) 
		{
			return 1;	# Success
		}
		if ( /([0-9]+)\.([0-9]+)\.([0-9]+)/ ) 
		{
			return 1;	# Success
		}
		if ( /([0-9]+)\.([0-9]+)/ ) 
		{
			return 1;	# Success
		}
	}
	return 0;	# failure.
}


# Retrieve an IPV4 address in standard 'dot' notation from stdin.
# Perform simple IP address format validation.
#
# returns:
#	IP address string.
#

sub Get_IP_Addr($$)
{
	my($interface) = shift();
	my($default_ip) = shift();

	my($ip,$idx);

	# acquire a valid IP address.
	# sadly last & redo caused runtime errors?

	do 
	{
		if ("$default_ip" ne "")
		{
			print "Enter IPV4 address in dot notation (or dhcp) for $interface [$default_ip]: ";
		} else {
			print "Enter IPV4 address in dot notation (or dhcp) for $interface: ";
		}
		chomp($ip = <STDIN>);
		$ip=remove_whitespace($ip);

		if ( length($ip) == 0 && "$default_ip" ne "" ) 
		{
			$ip = $default_ip;
			$_ = "y";
		}
		else 
		{
			# verify there are enough chars for a valid IP address
			if ( "$ip" ne "dhcp" && Validate_IP_Addr($ip) == 0 ) 
			{
				print("Bad IPV4 address '$ip'\n");
				$_ = "n";
			}
			else 
			{
				do
				{
					# require a response
					print("Is IPV4 address '$ip' correct? (y/n): ");
					chomp($_ = <STDIN>);
					$_=remove_whitespace($_);
				} until (/[YyNn]/);
			}
		}
	} until (/[Yy]/);
	LogPrint "Enter IPV4 address in dot notation for $interface: -> $ip\n";

	return $ip;
}

# Retrieve an IPV4 netmask in standard 'dot' notation from stdin.
# Perform simple IP address format validation.
#
# returns:
#	IP address string.
#

sub Get_IP_Addr_Netmask($$)
{
	my($interface) = shift();
	my($ipaddr) = shift();

	my($idx,$default_netmask,$dot_count);
	my $netmask;

	if ( "$ipaddr" eq "dhcp" ) {
		return "";
	}
	$default_netmask = `/usr/lib/opa/tools/opaipcalc --netmask $ipaddr`;
	$default_netmask =~ s/NETMASK=//;
	$default_netmask =~ s/\n//;
	$_ = $ipaddr;		# setup for translate & other cmds
	$dot_count=(tr/\.//);
	do 
	{
		print "Enter IPV4 netmask in dot notation for $interface $ipaddr [$default_netmask]: ";
		chomp($netmask = <STDIN>);
		$netmask=remove_whitespace($netmask);
		$_=$netmask;

		if ( length($netmask) == 0 ) 
		{
			$netmask = $default_netmask;
			print("Is IPV4 netmask '$netmask' correct? (y/n): ");
			chomp($_ = <STDIN>);
			$_=remove_whitespace($_);
		}
		else 
		{
			# verify there are enough chars for a valid IP address
			if ( Validate_IP_Addr($netmask) == 0 ) 
			{
				print("Bad IPV4 netmask: '$netmask'\n");
				$_ = "n";
			}
			elsif ($dot_count != (tr/\.//))
			{
				print("Inappropriate IPV4 netmask for $ipaddr: '$netmask'\n");
				$_ = "n";
			}
			else 
			{
				print("Is IPV4 netmask '$netmask' correct? (y/n): ");
				chomp($_ = <STDIN>);
				$_=remove_whitespace($_);
			}
		}
	} until (/[Yy]/);
	LogPrint "Enter IPV4 netmask in dot notation for $interface $ipaddr [$default_netmask]: -> $netmask\n";
	return $netmask;
}

# return the next sequential IPV4 address. Last numeric field is incremented.
#
# Assumes a valid dot notation IP address (e.g., 7.7.7.240)
# Increment the 'host' number ('240' in the example) by 1.
#  7.7.7.240 --> 7.7.7.241
#
# input:
#	base IP address in 'dot' notation.
# output:
#	next IP address

sub NextIPaddr($)
{
	my($base) = shift();

	my($next,$hostnum,$idx,$len);

	if ( "$base" eq "dhcp" ) {
		return "$base";
	}
	# locate right-most '.'
	$idx = rindex($base, ".");
	Abort "NextIPaddr: Bad IPV4 address ".$base
		if ($idx == -1);

	$idx += 1;	# move past the dot to the last numeric field portion of
				# the IP address.

	# extract the host number
	$len = length($base);
	$hostnum = substr($base, ($idx), ($len - $idx));

	$hostnum += 1;	# next host number

	# replace the last numeric field with the incremented host number
	$next = $base;
	substr($next,$idx,length($hostnum)) = $hostnum;

	DebugPrint("Next IP '$next'\n");

	return $next
}

# return the next sequential interface name. Last numeric field is incremented.
# if the final field is not numeric, returns ""
sub NextInterface($)
{
	my($base) = shift();

	my($next,$hostnum,$idx,$len);
	my $number;
	my $prefix;

	$_ = $base;
	if ( ! /.*([0-9]+)$/ ) 
	{
		# non numeric name, can't auto-increment
		return "";
	}
	$prefix = $base;
	$prefix =~ s/(.*)([0-9]+)$/$1/;
	$number = $base;
	$number =~ s/(.*)([0-9]+)$/$2/;

	$number += 1;	# next intf number

	return "$prefix$number";
}

# build the ifcfg file for a network device
sub Build_ifcfg($$$)
{
	my($device) = shift();		# device name
	my($ipaddr) = shift();		# ip address for device or "dhcp"
	my($netmask) = shift();		# ip address netmask for device

	my($target, $SysCmd);
	my ($temp);

	$target = "$NETWORK_CONF_DIR/ifcfg-$device";
	print("Creating ifcfg-$device for $ipaddr mask $netmask\n\n");

	if ( "$CUR_DISTRO_VENDOR" eq "UnitedLinux" || "$CUR_DISTRO_VENDOR" eq "SuSE") {
		if ( "$ipaddr" eq "dhcp" ) {
			# append boot protocol type
			$SysCmd = "echo \"BOOTPROTO=\'dhcp\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
		} else {
			# append boot protocol type
			$SysCmd = "echo \"BOOTPROTO=\'static\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# append the device instance internet protocol address
			$SysCmd = "echo \"IPADDR=\'$ipaddr\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# append the netmask
			$SysCmd = "echo \"NETMASK=\'$netmask\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# append the network
			$temp = `/usr/lib/opa/tools/opaipcalc --network $ipaddr $netmask`;
			chomp($temp);
			$temp =~ s/NETWORK=//;
			$SysCmd = "echo \"NETWORK=\'$temp\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# append the broadcast
			$temp = `/usr/lib/opa/tools/opaipcalc --broadcast $ipaddr $netmask`;
			chomp($temp);
			$temp =~ s/BROADCAST=//;
			$SysCmd = "echo \"BROADCAST=\'$temp\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			$SysCmd = "echo \"REMOTE_IPADDR=\'\'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
		}

		$SysCmd = "echo \"STARTMODE=\'hotplug\'\" >> $target";
		DebugPrint("cmd '$SysCmd'\n");
		system $SysCmd;

		$SysCmd = "echo \"WIRELESS='no'\" >> $target";
		DebugPrint("cmd '$SysCmd'\n");
		system $SysCmd;

		# SLES11 and newer have IPOIB_MODE option in ifcfg
		if ( "$CUR_VENDOR_VER" eq "ES123" ) {
			$SysCmd = "echo \"IPOIB_MODE='connected'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
			$SysCmd = "echo \"MTU=65520\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
		} else {
			$SysCmd = "echo \"IPOIB_MODE='datagram'\" >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
			NormalPrint "Note: IPoIB Mode is Datagram\n";
		}
	} else {
		# Append the device instance name
		$SysCmd = "echo DEVICE=$device > $target";
		DebugPrint("cmd '$SysCmd'\n");
		system $SysCmd;

		$SysCmd = "echo \"TYPE=\'InfiniBand\'\" >> $target";
                DebugPrint("cmd '$SysCmd'\n");
                system $SysCmd;

		if ( "$ipaddr" eq "dhcp" ) {
			$SysCmd = "echo BOOTPROTO=dhcp >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			$SysCmd = "echo DHCPCLASS= >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
		} else {

			$SysCmd = "echo BOOTPROTO=static >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# Append the device instance Internet Protocol address
			$SysCmd = "echo IPADDR=$ipaddr >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# append the network,broadcast
			$SysCmd = "/usr/lib/opa/tools/opaipcalc --network --broadcast $ipaddr $netmask >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;

			# append the netmask
			$SysCmd = "echo NETMASK=$netmask >> $target";
			DebugPrint("cmd '$SysCmd'\n");
			system $SysCmd;
		}

		$SysCmd = "echo ONBOOT=yes >> $target";
		DebugPrint("cmd '$SysCmd'\n");
		system $SysCmd;

		$SysCmd = "echo CONNECTED_MODE=no >> $target";
		DebugPrint("cmd '$SysCmd'\n");
		system $SysCmd;
#		$SysCmd = "echo MTU=65520 >> $target";
#		DebugPrint("cmd '$SysCmd'\n");
#		system $SysCmd;
		NormalPrint "Note: IPoIB Mode is Datagram\n";
	}

	system "chown $OWNER $target";
	system "chgrp $GROUP $target";
	system "chmod ugo=r,u=rw $target";
}

sub Config_IP_Manually($$)
{
	my($compname) = shift();
	my($sampledev) = shift();

	print "\n$compname requires an ifcfg file for each $compname device instance.\n";
	print ("Manually create files such as '$NETWORK_CONF_DIR/ifcfg-$sampledev'\n");
}


sub Exist_ifcfg($)
{
	my($prefix) = shift();

	my $ifcfg_wildcard="$NETWORK_CONF_DIR/ifcfg-$prefix"."[0-9]*";
	return ( `ls $ifcfg_wildcard 2>/dev/null` ne "" );
}

#
# Generate the network interface config files for IP over IB
#	/etc/sysconfig/network-scripts/ifcfg-ibl1
#
# Assign IP (Internet Protocol) addresses in standard 'dot' notation to
# IP over IB device instances. Create IP over IB 'ifup ibX' configuration files
# located in '/etc/sysconfig/network-scripts' for each IP over IB port.
#
# **** Currently - ONLY static IP address assignment is supported.
#
# inputs:
#	[0] == are we reconfiguring, if 1, allows editing of existing ifcfg files
#
# outputs:
#	none.
#
sub Config_ifcfg($$$$$)
{
	my($reconfig) = shift();
	my($compname) = shift();
	my($prefix) = shift();
	my($firstdev) = shift();
	my($showoptions) = shift();

	my($max_ports,$port,$a,$inp,$seq,$intf_seq,$default_intf);
	my($netmask);
	my($ipaddr) = "";
	my($interface) = "";
	my(%interfaces) = ();
	my $config_dir;

	$max_ports = 0;
			
	# Check if ifcfg files are present
	my $ifcfg_wildcard="$NETWORK_CONF_DIR/ifcfg-$prefix"."[0-9]*";
	if ( `ls $ifcfg_wildcard 2>/dev/null` ne "" )
	{
		if ($reconfig)
		{
			# always prompt regardless of previous check_keep_config answer
			clear_keep_config("$ifcfg_wildcard");
		}
		if (! $reconfig 
			|| check_keep_config("$ifcfg_wildcard", "$compname ifcfg files", "y"))
		{
			print "Leaving $ifcfg_wildcard unchanged...\n";
			return;
		} 
		print "removing $ifcfg_wildcard\n";
		system "rm -f $ifcfg_wildcard";
	}
	if (GetYesNo("Configure $compname IPV4 addresses now?", "n") == 0)
	{
		# If user answered 'no', then reluctantly bail.
		Config_IP_Manually("$compname","$prefix$firstdev");
		return;
	}

	if ( $showoptions != 0 )
	{
		printf ("\nYou may configure an $compname interface for each HFI port\n");
		printf ("Or you may select to have $compname only run on some HFI ports\n");
		printf ("Or you may select to configure redundant HFI ports with a\n");
		printf ("pair of HFI ports running a single $compname interface\n");
	}
	do
	{
		printf ("How many $compname interfaces would you like to configure? [1]: ");

		$inp = <STDIN>;
		$inp=remove_whitespace($inp);

		if ( length($inp) == 0 ) 
		{
			$max_ports=1;
		} elsif ($inp < 0 || $inp > $MAX_HFI_PORTS)
		{
			printf ("You must specify a number between 0 and $MAX_HFI_PORTS\n");
		} elsif ($inp == 0) {
			LogPrint "How many $compname interfaces would you like to configure? -> $inp\n";
			if (GetYesNo("You specified 0, would you like to skip IP address configuration?", "n") == 1)
			{
				# If user answered to skip, then reluctantly bail.
				Config_IP_Manually("$compname","$prefix$firstdev");
				return;
			}
		} else {
			$max_ports=$inp;
			LogPrint "How many $compname interfaces would you like to configure? -> $inp\n";
		}
	} while ($max_ports == 0);

	print "\nAbout to create $compname ifcfg files in $NETWORK_CONF_DIR\n";

	# Does the user want sequential IP address assignment starting at a base
	# IP address or specify an IP address for each HFI port (a.k.a. IPoIB device
	# instance). 

	if ( $max_ports > 1 ) {
		$intf_seq = GetYesNo("Configure interface names sequentially starting with $prefix$firstdev?", "y");
		$seq = GetYesNo("Assign Internet Addresses sequentially from a base IP address?", "y");
	} else {
		$intf_seq = GetYesNo("Use interface name $prefix$firstdev?", "y");
		$seq = 1;	# doesn't matter
	}

	# Allocate IP addresses and create the network config files '$prefix[firstdev...n]'.

	for($a=$firstdev; $a < $max_ports+$firstdev; $a++)
	{
		if ($intf_seq)
		{
			$interface="$prefix$a";
		} else {
			$default_intf = $interface;
			$interface = "";
			do {
				if ($default_intf eq "" )
				{
					print "Enter $compname interface name: ";
				} else {
					print "Enter $compname interface name [$default_intf]: ";
				}

				chomp($inp = <STDIN>);
				$inp=remove_whitespace($inp);
				if ( length($inp) == 0 )
				{
					$inp=$default_intf;
				}
				if ("$inp" eq "" )
				{
					printf "You must enter an interface name, such as $prefix$firstdev\n";
				} else {
					if (exists $interfaces{$inp})
					{
						print "You have already used $interface, specify a different name\n";
					} else {
						$interface=$inp;
						$interfaces{$interface} = 1;
					}
				}
			} while ("$interface" eq "");
		}
		LogPrint "Enter $compname interface name [$default_intf]: -> $interface\n";
		if ( $seq == 0 || $a == $firstdev) 
		{
			# not sequential assignment, get each IP addr.
			$ipaddr = Get_IP_Addr($interface, $ipaddr);
			$netmask = Get_IP_Addr_Netmask($interface, $ipaddr);
		}

		Build_ifcfg($interface, $ipaddr, $netmask);
		# make sure future prompts start fresh and don't auto remove
		clear_keep_config("$ifcfg_wildcard");

		# generate the next sequential IP address
		$ipaddr = NextIPaddr($ipaddr);
		$interface = NextInterface($interface);
	}
}

# Remove ifcfg files.
# driver should have already been unloaded.
#
sub Remove_ifcfg($$$)
{
	my($WhichDriver) = shift();	# driver name
	my($compname) = shift();
	my($prefix) = shift();

	# This could be an 'update' where we might not want to clobber the
	# IPoIB config files.

	my $ifcfg_wildcard="$NETWORK_CONF_DIR/ifcfg-$prefix"."[0-9]*";
	if ( `ls $ifcfg_wildcard 2>/dev/null` ne "" )
	{
		if (check_keep_config("$ifcfg_wildcard", "$compname ifcfg files", "y"))
		{
			print "Keeping $compname ifcfg files ...\n";
		} else {
			print "removing $ifcfg_wildcard\n";
			system "rm -f $ifcfg_wildcard";
		}
	}
}

sub check_network_config()
{
	my $nm=read_simple_config_param("/etc/sysconfig/network/config", "NETWORKMANAGER");
	if ( "$nm" eq "yes" ) {
		print RED "Please set NETWORKMANAGER=no in /etc/sysconfig/network/config", RESET "\n";
		HitKeyCont;
	}
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# =============================================================================
# The functions and constants below assist in editing modules.conf or
# modprobe.conf to add IB specific entries

my $MODULE_CONF_FILE = "/etc/modules.conf";
my $MODULE_CONF_DIST_FILE;
my $DRACUT_EXE_FILE = "/usr/bin/dracut";
if (substr($CUR_OS_VER,0,3) eq "2.6")
{
	$MODULE_CONF_FILE = "/etc/modprobe.conf";
	$MODULE_CONF_DIST_FILE = "/etc/modprobe.conf.dist";
	$DRACUT_EXE_FILE = "/sbin/dracut";
}
if (-f "$(MODULE_CONF_FILE).local")
{
	$MODULE_CONF_FILE = "$(MODULE_CONF_FILE).local";
}
my $OPA_CONF="modules.conf";	## additions to modules.conf

# marker strings used in MODULES_CONF_FILE
# for entries added by installation
my $START_DRIVER_MARKER="OPA Drivers Start here";
my $END_DRIVER_MARKER="OPA Drivers End here";

# Keep track of whether we already did edits to avoid repeated edits
my $DidConfig=0;

# This code is from OFED, it removes lines related to IB from
# modprobe.conf.  Used to prevent distro specific effects on OFED.
sub disable_distro_ofed()
{
	if ( "$MODULE_CONF_DIST_FILE" ne "" && -f "$MODULE_CONF_DIST_FILE" ) {
		my $res;

		$res = open(MDIST, "$MODULE_CONF_DIST_FILE");
		if ( ! $res ) {
			NormalPrint("Can't open $MODULE_CONF_DIST_FILE for input: $!");
			return;
		}
		my @mdist_lines;
		while (<MDIST>) {
			push @mdist_lines, $_;
		}
		close(MDIST);

		$res = open(MDIST, ">$MODULE_CONF_DIST_FILE");
		if ( ! $res ) {
			NormalPrint("Can't open $MODULE_CONF_DIST_FILE for output: $!");
			return;
		}
		foreach my $line (@mdist_lines) {
			chomp $line;
			if ($line =~ /^\s*install ib_core|^\s*alias ib|^\s*alias net-pf-26 ib_sdp/) {
				print MDIST "# $line\n";
			} else {
				print MDIST "$line\n";
			}
		}
		close(MDIST);
	}
}

# =============================================================================
# The functions and constants below assist in editing limits.conf
# to add IB specific entries related to memory locking

my $LIMITS_CONF_FILE = "/etc/security/limits.conf";
my $LIMITS_CONF="limits.conf";	## additions to limits.conf

# marker strings used in LIMITS_CONF_FILE
# for entries added by installation
my $START_LIMITS_MARKER="OPA Settings Start here";
my $END_LIMITS_MARKER="OPA Settings End here";

# Keep track of whether we already did edits to avoid repeated edits
my $DidLimits=0;

# Path to opasystemconfig
my $OPA_SYSTEMCFG_FILE = "/sbin/opasystemconfig";

# remove iba entries from modules.conf
sub remove_limits_conf()
{
	$DidLimits = 0;
	if ( -e "$LIMITS_CONF_FILE") {
		if (check_keep_config($LIMITS_CONF_FILE, "", "y"))
		{
			print "Keeping /$LIMITS_CONF_FILE changes ...\n";
		} else {
			print "Modifying $LIMITS_CONF_FILE ...\n";
			if ( -e "$OPA_SYSTEMCFG_FILE" ) {
			     system("$OPA_SYSTEMCFG_FILE --disable Memory_Limit");
			}
		}
	}
}

#
# Override the system's standard udev configuration to allow
# different access rights to some of the infiniband device files.
#
my $UDEV_RULES_DIR ="/etc/udev/rules.d";
my $UDEV_RULES_FILE = "05-opa.rules";
my $Default_UserQueries = 0;

my $udev_perm_string = "Allow non-root users to access the UMAD interface?";

AddAnswerHelp("UserQueries", "$udev_perm_string");

sub install_udev_permissions($)
{
	my ($srcdir) = shift(); # source directory.
	my $SourceFile;
	my $Context;
	my $Cnt;

	if ($Default_UserQueries == 0) {
		$Default_UserQueries = GetYesNoWithMemory("UserQueries",0,"$udev_perm_string", "y");
	}

	if ($Default_UserQueries > 0) {
                # Installation of udev will be taken care during RPM installation, we just have to set
                setup_env("OPA_UDEV_RULES", 1);
	} elsif ( -e "$UDEV_RULES_DIR/$UDEV_RULES_FILE" ) {
		#update environment variable accordingly
		setup_env("OPA_UDEV_RULES", 0);
	} else {
		# do nothing
		setup_env("OPA_UDEV_RULES", -1);
	}
}

sub remove_udev_permissions()
{
	remove_file("$UDEV_RULES_DIR/$UDEV_RULES_FILE");
}

#
# Ensures OPA drivers are incorporated in the initial ram disk.
#
my $CallDracut = 0;

sub rebuild_ramdisk()
{
	# Just increase the count. We will do the rebuild at the end of the script.
	$CallDracut++;
}

sub do_rebuild_ramdisk()
{
	if ($CallDracut && -d '/boot') {
		my $cmd = $DRACUT_EXE_FILE . ' --stdlog 0';
		if ( -d '/dev') {
			$cmd = $DRACUT_EXE_FILE;
		}
		#name of initramfs may vary between distros, so need to get it from lsinitrd
		my $current_initrd = `lsinitrd 2>&1 | head -n 1`;
		my ($initrd_prefix) = $current_initrd =~ m/\/boot\/(\w+)-[\w\-\.]+.*/;
		my $initrd_suffix = "";
                if ($current_initrd =~ m/\.img[':]/) {
                        $initrd_suffix = ".img";
                }
		my $tmpfile = "/tmp/$initrd_prefix-$CUR_OS_VER$initrd_suffix";

		if ( -e $cmd ) {
			do {
				NormalPrint("Rebuilding boot image with \"$cmd -f $tmpfile $CUR_OS_VER\"...\n");
				# Try to build a temporary image first as a dry-run to make sure
				# a failed run will not destroy an existing image.
				if (system("$cmd -f $tmpfile $CUR_OS_VER") == 0 && system("mv -f $tmpfile /boot/") == 0) {
					NormalPrint("New initramfs installed in /boot.\n");
					NormalPrint("done.\n");
					return;
				} else {
					NormalPrint("failed.\n");
				}
			} while(GetYesNo("Do you want to retry?", "n"));
			$exit_code = 1;
		} else {
			NormalPrint("$cmd not found, cannot update initial ram disk.");
			$exit_code = 1;
		}
	}
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ===========================================================================
# Host Tools

# capture host information for problem report
sub capture_report($)
{
	my($req_compname) = shift();

	my $result;
	my $inp;
	my $detail;

	if ( ! -e "$BIN_DIR/opacapture" ) {
		printf("$req_compname not installed on this system\n");
		printf("Unable to Generate Supporting Information\n");
		HitKeyCont;
		return;
	}
	do {
		printf ("\n\nEnter Filename to Generate [q to quit] : ");
		$inp = <STDIN>;
		$inp=remove_whitespace($inp);
		chomp $inp;
		$_ = $inp;
			
		if (/^[Qq]$/) {
			return;
		}

		if ( length($inp) == 0 ) {
			next;
		}

		LogPrint "Capturing $INT_VERSION Report to $inp\n";
		$detail=GetNumericValue("Capture detail level (1-Normal 2-Fabric 3-Fabric+FDB 4-Analysis):", 1, 1, 4);
		close_log;
		$result = system "$BIN_DIR/opacapture -d $detail $inp";
		if ( $result != 0 ) {
			printf("\nError generating $inp\n");
		}
	} while ($result != 0);
	open_log;
	HitKeyCont;
}

# invoke FastFabric TUI
my $FabricSetupScpFromDir=".";

sub run_fastfabric($)
{
	my($req_compname) = shift();

	if ( ! -e "$BIN_DIR/opafastfabric" ) {
		printf("$req_compname not installed on this system\n");
		printf("Unable to perform FastFabric (Host/Chassis/Switch Setup/Admin)\n");
		HitKeyCont;
		return;
	}
	system("$BIN_DIR/opafastfabric --fromdir $FabricSetupScpFromDir");
	return;
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# =============================================================================
# The functions and constants below assist in using RPM files

# on platforms without 32 bit app on 64 bit OS support, these are ''
# _glob is a glob pattern version which can be used to match rpm names
# when building rpms the simple _cpu32 values should be used
my $suffix_64bit = "";	# suffix for rpm name for 64 bit rpms

my $rpm_check_dependencies = 1;	# can be set to 0 to disable rpm_check_os_prereqs

sub rpm_query_param($);
# TBD or
# my $RPM_ARCH = rpm_query_param('_target_cpu');
# chomp $RPM_ARCH;
my $RPM_ARCH=my_tolower("$ARCH");
if ( "$RPM_ARCH" eq "ia32" ) {
	$RPM_ARCH = rpm_query_param('_target_cpu');
	#$RPM_ARCH=`uname -m`; # or i386
	chomp $RPM_ARCH;
}
my $RPM_KERNEL_ARCH = `uname -m`; # typically matches $RPM_ARCH
chomp $RPM_KERNEL_ARCH;

# return array of cmds for verification during init
sub rpm_get_cmds_for_verification()
{
	return ("/bin/rpm"); # Command paths
}

# version string for kernel used in RPM filenames uses _ instead of -
sub rpm_tr_os_version($)
{
	my $osver = shift();	# uname -r style output
	$osver =~ s/-/_/g;
	return "$osver";
}

# query a parameter of RPM tools themselves
sub	rpm_query_param($)
{
	my $param = shift();	# parameter name: such as _mandir, _sysconfdir, _target_cpu
	my $ret = `$RPM --eval "%{$param}"`;
	chomp $ret;
	return $ret;
}

# query an attribute of the RPM file
sub	rpm_query_attr($$)
{
	my $rpmfile = shift();	# .rpm file
	my $attr = shift();	# attribute name: such as NAME or VERSION

	if ( ! -f "$rpmfile" ) {
		return "";
	}
	return `$RPM --queryformat "[%{$attr}]" -qp $rpmfile 2>/dev/null`;
}

# query an attribute of the installed RPM package
sub	rpm_query_attr_pkg($$)
{
	my $package = shift();	# installed package
	my $attr = shift();	# attribute name: such as NAME or VERSION

	return `$RPM --queryformat "[%{$attr}]" -q $package 2>/dev/null`;
}

# determine if rpm parameters will allow srpms to build debuginfo rpms
sub rpm_will_build_debuginfo()
{
	# If debug_package is set to nil in .rpmmacros, srpms will not generate
	# -debuginfo rpms, so they will not be available to install
	return (rpm_query_param('debug_package') ne "");
}

# get NAME of RPM file
sub rpm_query_name($)
{
	my $rpmfile = shift();	# .rpm file

	return rpm_query_attr($rpmfile, "NAME");
}

sub rpm_query_version_release($)
{
	my $rpmfile = shift();	# .rpm file

	my $ver = rpm_query_attr($rpmfile, "VERSION");
	my $rel = rpm_query_attr($rpmfile, "RELEASE");
	return "${ver}-${rel}";
}

# get VERSION-RELEASE of installed RPM package
sub rpm_query_version_release_pkg($)
{
	my $package = shift();	# installed package

	my $ver = rpm_query_attr_pkg($package, "VERSION");
	my $rel = rpm_query_attr_pkg($package, "RELEASE");
	return "${ver}-${rel}";
}

# return NAME-VERSION-RELEASE.ARCH
sub rpm_query_full_name($)
{
	my $rpmfile = shift();	# .rpm file

	if ( ! -f "$rpmfile" ) {
		return "";
	}
	return `$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}]' -qp $rpmfile 2>/dev/null`;
}

# beware, this could return more than 1 name
#sub rpm_query_full_name_pkg($)
#{
#	my $package = shift();	# installed package
#	return `$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}]' -q $package 2>/dev/null`;
#}

sub rpm_get_cpu_arch($)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed

	if ("$mode" eq "user" || "$mode" eq "any" || "$mode" eq "firmware") {
		return $RPM_ARCH;
    } else {
		return $RPM_KERNEL_ARCH;
	}
}

my $last_checked;	# last checked for in rpm_is_installed
sub rpm_is_installed($$)
{
	my $package = shift();	# package name
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $rc;
	my $cpu;

	if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") {
               return 1;
	}

	$cpu = rpm_get_cpu_arch($mode);
	if ("$mode" eq "any" ) {
		# any variation is ok
		DebugPrint("$RPM -q $package > /dev/null 2>&1\n");
		$rc = system("$RPM -q $package > /dev/null 2>&1");
		$last_checked = "any variation";
	} elsif ("$mode" eq "user" || "$mode" eq "firmware" || $package eq "hfi2") {
		# the above check on hfi2 is a temporary work around because the current hfi2 kernel rpm has no kernel version
		# number in file name (see STL-14187). After we resolve the issue, we shall remove the above check on hfi2
		# verify $cpu version or noarch is installed
		DebugPrint "$RPM --queryformat '[%{ARCH}\\n]' -q $package 2>/dev/null|egrep '^$cpu\$|^noarch\$' >/dev/null 2>&1\n";
		$rc = system "$RPM --queryformat '[%{ARCH}\\n]' -q $package 2>/dev/null|egrep '^$cpu\$|^noarch\$' >/dev/null 2>&1";
		$last_checked = "for $mode $cpu or noarch";
	} else {
		# $mode is kernel rev, verify proper kernel version is installed
		# for kernel packages, RELEASE is kernel rev
		my $release = rpm_tr_os_version($mode);
		DebugPrint "$RPM --queryformat '[%{VERSION}\\n]' -q $package 2>/dev/null|egrep '$release' >/dev/null 2>&1\n";
		$rc = system " $RPM --queryformat '[%{VERSION}\\n]' -q $package 2>/dev/null|egrep '$release' >/dev/null 2>&1";
		$last_checked = "for kernel $release";
	}
	DebugPrint("Checked if $package $mode is installed: ".(($rc==0)?"yes":"no")."\n");
	return 0 == $rc;
}

sub rpm_is_installed_list($@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- verifies any variation of package is installed
	my @package_list = @_;	# package names

	foreach my $package ( @package_list )
	{
		if ( !  rpm_is_installed($package, $mode) ) {
			return 0;
		}
	}
	return 1;
}

# return 0 on success, number of errors otherwise
sub rpm_check_os_prereqs_internal($$@)
{
	my $mode = shift();	# default mode
	my $message = shift();
	my @package_list = @_;	# package names
	my $err=0;
	
	if ( ! $rpm_check_dependencies ) {
		return 0;
	}
	# Check installation requirements
	DebugPrint "Checking prereqs $message: @package_list\n";
	for my $package_info ( @package_list )
	{
		# expand any alias in package_info
		my $full_package_info="";
		my @alternatives = (split ('\|',$package_info));
		for my $altpackage_info ( @alternatives )
		{
			my ($package, $details) = (split (' ',$altpackage_info,2));
			if ($details ne "") {
				$details=" $details";
			}
			if ( "$full_package_info" ne "" ) {
				$full_package_info = "$full_package_info|";
			}

			# expand "g77" alias for various fortran compilers
			# and "libgfortran" alias for various fortran library
			if ("$package" eq "g77" ) {
				# on RHEL4u5-6: gcc4-gfortran, gcc-g77
				# on RHEL5.1: gcc-gfortran, compat-gcc-34-g77
				# on RHEL5.2: gcc-gfortran
				# on RHEL5.3: gcc43-gfortran
				# on sles10sp1-2: gcc-fortran
				# on sles11: gcc-fortran
				$full_package_info = "${full_package_info}gcc4-gfortran$details|gcc-g77$details|gcc-gfortran$details|compat-gcc-34-g77$details|gcc43-gfortran$details|gcc42-gfortran$details|gcc-fortran$details|gcc42-fortran$details|gcc43-fortran$details"

			} elsif ("$package" eq "libgfortran") {
				# on RHEL4u5-6: libgfortran
				# on RHEL5.1: libgfortran
				# on RHEL5.2: libgfortran
				# on RHEL5.3: libgfortran43
				# on sles10sp1-2: libgfortran
				# on sles11sp0-1: libgfortran43
				# on sles11sp2: libgfortran46
				# TBD - openSUSE11.2 has libgfortran44
                                # sles12sp0: libgfortran3-4
				$full_package_info = "${full_package_info}libgfortran$details|libgfortran42$details|libgfortran43$details|libgfortran46$details|compat-gcc-34-g77$details|libgfortran3$details";
			} else {
				$full_package_info = "${full_package_info}$altpackage_info";
			}
		}

		# now process the expanded list of alternatives
		DebugPrint "Checking prereq: $full_package_info\n";
		my $errmessage="";
		@alternatives = (split ('\|',$full_package_info));
		for my $altpackage_info ( @alternatives )
		{
			DebugPrint "Checking prereq: $altpackage_info\n";
			my ($package, $version, $pkgmode) = (split (' ',$altpackage_info));
			if ("$pkgmode" eq "") {
				$pkgmode = $mode;
			}

			# keep things simple for callers, handle distro specific namings
			
			# distro specific naming of libstdc++
			if ("$package" eq "libstdc++" && "$CUR_DISTRO_VENDOR" eq 'SuSE'
					&& "$CUR_VENDOR_VER" eq 'ES11') {
				# hack because CUR_VENDOR_VER doesn't actually contain the minor 
				# version any more...
				my $CUR_VENDOR_MINOR_VER = `grep PATCHLEVEL /etc/SuSE-release | cut -d' ' -f 3`;
				chop($CUR_VENDOR_MINOR_VER);
				if ($CUR_VENDOR_MINOR_VER eq '0' || $CUR_VENDOR_MINOR_VER eq '1') { $package="libstdc++43"; }
				if ($CUR_VENDOR_MINOR_VER eq '2' ) { $package="libstdc++46"; }
				if ($CUR_VENDOR_MINOR_VER eq '3' ) { $package="libstdc++6"; }
				# SLES11 SP3 has renamed libstdc++47 as libstdc++6
				# TBD - openSUSE has libstdc++42
				# TBD - openSUSE11.2 has libstdc++44
			} elsif ("$package" eq "libstdc++" && "$CUR_DISTRO_VENDOR" eq 'SuSE'
					&& ("$CUR_VENDOR_VER" eq 'ES12' || "$CUR_VENDOR_VER" eq 'ES121' || "$CUR_VENDOR_VER" eq 'ES122')) {
				$package="libstdc++6";
		 	} elsif ("$package" eq "libstdc++-devel" && "$CUR_DISTRO_VENDOR" eq 'SuSE'
					&& "$CUR_VENDOR_VER" eq 'ES11') {
				# hack because CUR_VENDOR_VER doesn't actually contain the minor 
				# version any more...
				my $CUR_VENDOR_MINOR_VER = `grep PATCHLEVEL /etc/SuSE-release | cut -d' ' -f 3`;
				chop($CUR_VENDOR_MINOR_VER);
				if ($CUR_VENDOR_MINOR_VER eq '0' || $CUR_VENDOR_MINOR_VER eq '1') { $package="libstdc++43-devel"; }
				if ($CUR_VENDOR_MINOR_VER eq '2' ) { $package="libstdc++46-devel"; }
				if ($CUR_VENDOR_MINOR_VER eq '3') { $package="libstdc++47-devel"; }
				# TBD - openSUSE has libstdc++42-devel
				# TBD - openSUSE11.2 has libstdc++44-devel
			}

			# distro specific naming of sysfsutils
			if ("$package" eq "sysfsutils" ) {
				if ("$CUR_DISTRO_VENDOR" ne 'SuSE' && "$CUR_DISTRO_VENDOR" ne 'redhat'
			    	&& "$CUR_DISTRO_VENDOR" ne 'fedora' && "$CUR_DISTRO_VENDOR" ne 'rocks') {
					$package="libsysfs";
				}
			}

			# distro specific naming of sysfsutils-devel
			# RHEL4 used sysfsutils-devel
			# SuSE uses sysfsutils
			# others use libsysfs-devel
			if ("$package" eq "sysfsutils-devel" ) {
				if (($CUR_DISTRO_VENDOR eq "SuSE")
					or ($CUR_DISTRO_VENDOR eq "redhat" and $CUR_VENDOR_VER eq "ES5")
	) {
        			$package = "sysfsutils";
    			} elsif (($CUR_DISTRO_VENDOR eq "rocks") or
        			($CUR_DISTRO_VENDOR eq "fedora") or
        			($CUR_DISTRO_VENDOR eq "redhat")) {
        				$package = "sysfsutils-devel";
    			} else {
        			$package = "libsysfs-devel";
    			}

			}

			if ("$pkgmode" eq "user") {
				# SLES10 and 11 -64bit rpms report ppc as ARCH
				$package="$package$suffix_64bit";
				if ( "$suffix_64bit" ne "" ) {
					$pkgmode="any";
				}
			}
			if (! rpm_is_installed($package, $pkgmode)) {
				if ( $errmessage ne "") {
					$errmessage="$errmessage\n OR ";
				}
				$errmessage = "$errmessage$package ($last_checked)";
			#} elsif ("$version" ne "" && "$version" ne "any") {
			#	# TBD - could be multiple versions of package installed
			#	# in which case this returns merged strings, not good
			#	my $ver = rpm_query_attr_pkg($package, "VERSION");
			#	TBD - string compare not the same as proper numeric compare
			#	if ($ver lt $version) {
			#		if ( $errmessage ne "") {
			#			$errmessage="$errmessage\n OR ";
			#		}
			#		$errmessage = "$errmessage$package version $version ($last_checked)";
			#	}
			} else {
				$errmessage="";
				last;
			}
		}
		if ( $errmessage ne "" ) {
			if (scalar(@alternatives) > 1) {
				$errmessage="$errmessage\n";
			}
			NormalPrint("$errmessage is required$message\n");
			$err++;
		}
	}
	return $err;
}

sub rpm_check_os_prereqs($$)
{
        no strict 'refs';
        my $comp = shift();
        my $mode = shift();
        my $list_name;
        my $array_ref;
        my @rpm_list = {};
        my $prereq_check = 0;

        if ( ! $rpm_check_dependencies ) {
                return 0;
        }

        $list_name=$comp."_prereq";
        $array_ref = $comp_prereq_hash{$list_name};
	#checking if prereq array exists
	#it assumed that it has no prereqs it array does not exist
        if ( $array_ref ) {
                @rpm_list = @{ $array_ref };
        }
        else{
                return 0;
        }

	#checking whether each entry in rpm_list is installed
        DebugPrint "Checking prereqs for $comp\n";
        foreach (@rpm_list){
                DebugPrint "Checking installation of $_\n";
		#Don't check dependencies for kernel RPMS if their installation is skipped
		if($user_space_only == 1){
                	if( "$_" =~ /kernel/ || "$_" =~ /kmod/ || "$_" eq "pciutils" ) {
				DebugPrint("Skipping check for $_ \n");
				next;
			}
		}
                if(!rpm_is_installed($_, $mode)){
                        NormalPrint("--> $comp requires $_ \n");
                        $prereq_check = 1;
                }
        }

        return $prereq_check;
}


sub rpm_check_build_os_prereqs($$@)
{
	my $mode = shift();
	my $build_info = shift();
	my @package_list = @_;	# package names
	return rpm_check_os_prereqs_internal($mode, " to build $build_info", @package_list);
}

# get list of package rpms installed
# the list could include multiple versions and/or multiple architectures
# and/or multiple kernel releases
# all entries in returned list are complete package names in the form:
#	NAME-VERSION-RELEASE.ARCH
sub rpms_installed_pkg($$)
{
	my $package=shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed

	my @lines=();
	my $cpu;

	$cpu = rpm_get_cpu_arch($mode);
	if ( "$mode" eq "any" ) {
		DebugPrint("$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null\n");
		open(rpms, "$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|");
	} elsif ("$mode" eq "user" || "$mode" eq "firmware") {
		DebugPrint("$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '\.$cpu\$|\.noarch\$' 2>/dev/null\n");
		open(rpms, "$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '\.$cpu\$|\.noarch\$' 2>/dev/null|");
	} else {
		# $mode is kernel rev, verify proper kernel version is installed
		# for kernel packages, RELEASE is kernel rev
		my $release = rpm_tr_os_version($mode);
		DebugPrint("$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '-$release\.$cpu\$' 2>/dev/null\n");
		open(rpms, "$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '-$release\.$cpu\$' 2>/dev/null|");
	}
	@lines=<rpms>;
	close(rpms);
	if ( $? != 0) {
		# query command failed, package must not be installed
		@lines=();
	}
	chomp(@lines);
	DebugPrint("package $package $mode: installed: @lines\n");
	return @lines;
}

# identify all possible variations of the package
sub rpm_variations($$)
{
	my $package=shift();
	my $mode = shift();	# "user", kernel rev, "firmware" or "any"
						# "any" checks if any variation of package is installed
	my @variations = ( $package );

	if ( ("$mode" eq "any" || "$mode" eq "user") && $suffix_64bit ne "") {
		@variations = (@variations, "$package$suffix_64bit");
	}
	return @variations;
}

# get list of package rpms installed
# the list could include multiple versions and/or multiple architectures
# and/or multiple kernel releases
# all entries in returned list are complete package names in the form:
#	NAME-VERSION-RELEASE.ARCH
sub rpms_variations_installed_pkg($$)
{
	my $package=shift();
	my $mode = shift();	

	my @result=();

	foreach my $p ( rpm_variations($package, $mode) ) {
		@result = ( @result, rpms_installed_pkg($p, $mode) );
	}
	return @result;
}

# determine if given rpm contains the given file
sub rpm_has_file($$)
{
	my $rpmfile = shift();	# .rpm file
	my $file = shift();		# file to look for in rpm

	if ( ! -f "$rpmfile" ) {
		return 0;
	}
	return (! system("$RPM -qlp $rpmfile 2>/dev/null | grep '/${file}\$' > /dev/null 2>&1"));
}

# return names of all installed RPMs matching the given partial name and filter
sub rpm_query_all($$)
{
	my $package = shift();
	my $filter = shift();

	my $res=` $RPM -qa 2>/dev/null|grep -i '$package'|grep '$filter'`;
	$res=~s/\n/ /g;
	return $res;
}

# uninstall all packages which match package partial name and filter
# returns 0 on sucess (or package not installed), != 0 on failure
sub rpm_uninstall_matches($$$;$)
{
	my $name = shift();	# for use only in log messages
	my $package = shift();	# part of package name
	my $filter = shift();	# any additional grep filter
	my $options = shift();	# additional rpm command options
	my $rpms = rpm_query_all("$package", "$filter");

	if ( "$rpms" ne "" ) {
		LogPrint "uninstalling $name: $RPM -e $rpms\n";
		my $out =`$RPM -e $options $rpms 2>&1`;
		my $rc=$?;
		NormalPrint("$out");
		if ($rc != 0) {
			$exit_code = 1;
		}
		return $rc;
	} else {
		return 0;
	}
}

sub rpm_run_install($$$)
{
	my $rpmfile = shift();	# .rpm file
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	my $options = shift();	# additional rpm command options
						# if " -U " is part of these options, -U will be
						# unconditionally used, even if the rpm is not
						# already installed.  Otherwise -U will only be
						# used if the rpm is installed.  Note that some OFED
						# rpms do not properly handle -U for actual upgrades.
						# Hence for OFED we tend to uninstall the old rpms first
						# and the rpm -i is used to install here.

	my $Uoption= 0;

	if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") {
		return;
	}

	# We require whitespace around -U so its not mistaken for filenames or other
	# multi-letter options
	if ($options =~ / -U /) {
		$Uoption=1;
		$options =~ s/ -U //;
	}
	
	if ( ! -e $rpmfile ) {
		NormalPrint "Not Found: $rpmfile $mode\n";
		return;
	}

	my $package = rpm_query_name($rpmfile);
	my $fullname = rpm_query_full_name($rpmfile);
	my $out;

	NormalPrint "installing ${fullname}...\n";

	my $upgrade=rpm_is_installed($package, $mode);
	if ( ! $upgrade ) {
		my @obsoletes = split /[[:space:]]+/, `$RPM --queryformat '[%{OBSOLETES}\\n]' -qp $rpmfile 2>/dev/null`;
		for my $p ( @obsoletes ) {
			next if ( "$p" eq "(none)" );	
			$upgrade |= rpm_is_installed($p, $mode);
			if ($upgrade) {
				last;
			}
		}
	}

	if( $Uoption || $upgrade ) {	
		# -U option will only update this exact package and architecture
		# when multiple architectures are installed, other architecture rpms
		# are not affected by -U, however --force is needed in that case
		# also need --force for reinstall case
		LogPrint "  $RPM -U --force $options $rpmfile\n";
		$out=`$RPM -U --force $options $rpmfile 2>&1`;
		if ( $? == 0 ) {
			NormalPrint("$out");
		} else {
			NormalPrint("ERROR - Failed to install $rpmfile\n");
			NormalPrint("$out");
			$exit_code = 1;
			HitKeyCont;
		}

	} else {
		# initial install of rpm
		# force not required, even if other architectures already installed
		if ("$ARCH" eq 'PPC64') {
			# PPC64 SLES10 needs --force
			$options='--force '."$options";
		}
		LogPrint "  $RPM -i $options $rpmfile\n";
		$out=`$RPM -i $options $rpmfile 2>&1`;
		if ( $? == 0 ) {
			NormalPrint("$out");
		} else {
			NormalPrint("ERROR - Failed to install $rpmfile\n");
			NormalPrint("$out");
			$exit_code = 1;
			HitKeyCont;
		}
	}
}

# returns 0 on sucess (or package not installed), != 0 on failure
# uninstalls all variations of given package
sub rpm_uninstall($$$$)
{
	my $package = shift();	# package name
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $options = shift();	# additional rpm command options
	my $verbosity = shift();	# verbose or silent
	my @fullnames = rpms_variations_installed_pkg($package, $mode); # already adjusts mode
	my $rc = 0;
	foreach my $fullname (@fullnames) {
		if ( "$verbosity" ne "silent" ) {
			print "uninstalling ${fullname}...\n";
		}
		LogPrint "$RPM -e $options $fullname\n";
		my $out=`$RPM -e $options $fullname 2>&1`;
		$rc |= $?;
		NormalPrint("$out");
		if ($rc != 0) {
			$exit_code = 1;
		}
	}
	return $rc;
}

# resolve rpm package filename for $mode
# rpmpath is a glob style absolute or relative path to the package
# including the package name, but excluding package version, architecture and
# .rpm suffix
# TBD - can restructure this as a loop for a list of paths to check
# for each in @( "-[0-9]*.${cpu}.rpm "-r[0-9]*.${cpu}.rpm" ... )
#     Print
#     file_glob("${rpmpath}${suffix}"
#     if match
#         exit loop
sub rpm_resolve($$)
{
	my $rpmpath = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- any variation found
	my $rpmfile;
	my $cpu;

	$cpu = rpm_get_cpu_arch($mode);
	if ("$mode" eq "user" || "$mode" eq "firmware") {
		# we expect 0-1 match, ignore all other filenames returned
		DebugPrint("Checking for $mode Rpm: ${rpmpath}-[0-9]*.${cpu}.rpm\n");
		$rpmfile = file_glob("${rpmpath}-[0-9]*.${cpu}.rpm");
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			DebugPrint("Checking for $mode Rpm: ${rpmpath}-r[0-9]*.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-r[0-9]*.${cpu}.rpm");
		}
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			DebugPrint("Checking for $mode Rpm: ${rpmpath}-trunk-[0-9]*.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-trunk-[0-9]*.${cpu}.rpm");
		}
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			# we expect 0-1 match, ignore all other filenames returned
			DebugPrint("Checking for $mode Rpm: ${rpmpath}-[0-9]*.noarch.rpm\n");
			$rpmfile = file_glob("${rpmpath}-[0-9]*.noarch.rpm");
			if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
				DebugPrint("Checking for $mode Rpm: ${rpmpath}-r[0-9]*.noarch.rpm\n");
				$rpmfile = file_glob("${rpmpath}-r[0-9]*.noarch.rpm");
			}
			if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
				DebugPrint("Checking for $mode Rpm: ${rpmpath}-trunk-[0-9]*.noarch.rpm\n");
				$rpmfile = file_glob("${rpmpath}-trunk-[0-9]*.noarch.rpm");
			}
		}
	} elsif ("$mode" eq "any" ) {
		# we expect 0-1 match, ignore all other filenames returned
		DebugPrint("Checking for User Rpm: ${rpmpath}-[0-9]*.*.rpm\n");
		$rpmfile = file_glob("${rpmpath}-[0-9]*.*.rpm");
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			DebugPrint("Checking for User Rpm: ${rpmpath}-r[0-9]*.*.rpm\n");
			$rpmfile = file_glob("${rpmpath}-r[0-9]*.*.rpm");
		}
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			DebugPrint("Checking for User Rpm: ${rpmpath}-trunk-[0-9]*.*.rpm\n");
			$rpmfile = file_glob("${rpmpath}-trunk-[0-9]*.*.rpm");
		}
	} else {
		my $osver = rpm_tr_os_version("$mode");	# OS version
		# we expect 1 match, ignore all other filenames returned
		if ( "$CUR_VENDOR_VER" eq 'ES122' || "$CUR_VENDOR_VER" eq 'ES123' || "$CUR_VENDOR_VER" eq 'ES124' || "$CUR_VENDOR_VER" eq 'ES125' ||"$CUR_VENDOR_VER" eq 'ES15' || "$CUR_VENDOR_VER" eq 'ES151' || "$CUR_VENDOR_VER" eq 'ES152' || "$CUR_VENDOR_VER" eq 'ES153' ) {
			DebugPrint("Checking for Kernel Rpm: ${rpmpath}-${osver}_k*.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-${osver}_k*.${cpu}.rpm");
		} else {
			DebugPrint("Checking for Kernel Rpm: ${rpmpath}-[0-9]*.[0-9][0-9].${osver}-[0-9]*.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-[0-9]*.[0-9][0-9].${osver}-[0-9]*.${cpu}.rpm");
		}
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			DebugPrint("Checking for Kernel Rpm: ${rpmpath}-${osver}-[0-9]*.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-${osver}-[0-9]*.${cpu}.rpm");
		}
		if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
			DebugPrint("Checking for Kernel Rpm: ${rpmpath}-trunk-[0-9]*-${osver}.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-trunk-[0-9]*-${osver}.${cpu}.rpm");
		}
		# the following is a temporary work around because the current hfi2 kernel rpm has no kernel version
		# number in file name (see STL-14187). After we resolve the issue, we shall remove the following 4 lines
		if ( $HFI2_INSTALL && ("$rpmfile" eq "" || ! -e "$rpmfile") ) {
			DebugPrint("Checking for Kernel Rpm: ${rpmpath}-[0-9]*.${cpu}.rpm\n");
			$rpmfile = file_glob("${rpmpath}-[0-9]*.${cpu}.rpm");
		}
	}
	VerbosePrint("Resolved $rpmpath $mode: $rpmfile\n");
	return $rpmfile;
}

sub rpm_exists($$)
{
	my $rpmpath = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- any variation found
	my $rpmfile;

	$rpmfile = rpm_resolve("$rpmpath", $mode);
	return ("$rpmfile" ne "" && -e "$rpmfile");
}

sub rpm_install_with_options($$$)
{
	my $rpmpath = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	my $options = shift();	# additional rpm command options
	my $rpmfile;

	if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") {
		return;
	}

	$rpmfile = rpm_resolve("$rpmpath", $mode);
	if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) {
		NormalPrint "Not Found: $rpmpath $mode\n";
	} else {
		if ("$mode" eq "user" || "$mode" eq "any" || "$mode" eq "firmware" ) {
			rpm_run_install($rpmfile, $mode, $options);
		} else {
			# kernel install
			if ("$CUR_DISTRO_VENDOR" eq 'SuSE' && 
			    $options !~ / --nodeps /) {
				# ofed1.3 only uses --nodeps on SuSE to workaround ksym
				# dependencies.
				# TBD - is this still needed?
				rpm_run_install($rpmfile, $mode, "--nodeps $options");
			} else {
				rpm_run_install($rpmfile, $mode, $options);
			}
		}
	}
}

# TBD - phase out this function (or get all callers to use same options)
sub rpm_install($$)
{
	my $rpmpath = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	
	rpm_install_with_options($rpmpath, $mode, "");
}

# verify the rpmfiles exist for all the RPMs listed
sub rpm_exists_list($$@)
{
	my $rpmdir = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- any variation found
	my @package_list = @_;	# package names

	foreach my $package ( @package_list )
	{
		if (! rpm_exists("$rpmdir/$package", $mode) ) {
			return 0;
		}
	}
	return 1;
}

sub rpm_install_list_with_options($$$@)
{
	my $rpmdir = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	my $options = shift();	# additional rpm command options
	my @package_list = @_;	# package names

	foreach my $package ( @package_list )
	{
		rpm_install_with_options("$rpmdir/$package", $mode, $options);
	}
}

# TBD - phase out this function (or get all callers to use same options)
sub rpm_install_list($$@)
{
	my $rpmdir = shift();
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	my @package_list = @_;	# package names

	rpm_install_list_with_options($rpmdir, $mode, "", @package_list);
}

# rpmpath_list is a list of glob style absolute or relative path to the packages
# including the package name, but excluding package version, architecture and
# .rpm suffix
sub rpm_install_path_list_with_options($$@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	my $options = shift();	# additional rpm command options
	my @rpmpath_list = @_;	# rpm pathnames

	foreach my $rpmpath ( @rpmpath_list )
	{
		rpm_install_with_options("$rpmpath", $mode, $options);
	}
}

# rpmpath_list is a list of glob style absolute or relative path to the packages
# including the package name, but excluding package version, architecture and
# .rpm suffix
# TBD - phase out this function (or get all callers to use same options)
sub rpm_install_path_list($@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- will install any variation found
	my @rpmpath_list = @_;	# rpm pathnames

	rpm_install_path_list_with_options($mode, "", @rpmpath_list);
}


# returns 0 on success (or rpms not installed), != 0 on failure
sub rpm_uninstall_list2($$$@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $options = shift();	# additional rpm command options
	my $verbosity = shift();	# verbose or silent
	my @package_list = @_;	# package names
	my $package;
	my $ret = 0;	# assume success

	foreach $package ( reverse(@package_list) )
	{
		$ret |= rpm_uninstall($package, $mode, $options, $verbosity);
	}
	return $ret;
}

# returns 0 on success (or rpms not installed), != 0 on failure
sub rpm_uninstall_list($$@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $verbosity = shift();	# verbose or silent
	my @package_list = @_;	# package names

	return rpm_uninstall_list2($mode, "", $verbosity, (@package_list));
}

# uninstall all rpms which match any of the supplied package names
# and based on mode and distro/cpu, 
# uninstall is done in a single command
# returns 0 on success (or rpms not installed), != 0 on failure
# Force to uninstall without any concern for dependency.
sub rpm_uninstall_all_list_with_options($$$@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $options = shift();	# additional rpm command options
	my $verbosity = shift();	# verbose or silent
	my @package_list = @_;	# package names
	my @uninstall = ();

	if ("$mode" eq "any") {
		$options .= "--allmatches";
	}
	foreach my $package ( @package_list )
	{
		foreach my $p ( rpm_variations($package, $mode) )
		{
			if (rpm_is_installed($p, $mode)) {
				if ("$mode" eq "any") {
					@uninstall = (@uninstall, $p);
				} else {
					@uninstall = (@uninstall, rpms_installed_pkg($p, $mode));
				}
			}
		}
	}
	
	if (scalar(@uninstall) != 0) {
		LogPrint "$RPM -e $options @uninstall\n";
		my $out=`$RPM -e $options @uninstall 2>&1`;
		my $rc=$?;
		NormalPrint("$out");
		if ($rc != 0) {
			$exit_code = 1;
		}
		return $rc;
	} else {
		LogPrint "None Found\n";
		return 0;	# nothing to do
	}
}

# uninstall all rpms which match any of the supplied package names
# and based on mode and distro/cpu.
# uninstall is done in a single command so dependency issues handled
# returns 0 on success (or rpms not installed), != 0 on failure
# TBD - phase out this function (or get all callers to use same options)
sub rpm_uninstall_all_list($$@)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $verbosity = shift();	# verbose or silent
	my @package_list = @_;	# package names

	rpm_uninstall_all_list_with_options($mode, "", $verbosity, @package_list);
}

# see if prereqs for building kernel modules are installed
# return 0 on success, 1 if missing dependencies
sub check_kbuild_dependencies($$)
{
	my $osver = shift();	# kernel rev
	my $srpm = shift();	# what trying to build
	my $dir = "/lib/modules/$osver/build";

	if ( ! $rpm_check_dependencies ) {
		return 0;
	}
	if ( ! -d "$dir/scripts" ) {
		NormalPrint "Unable to build $srpm: $dir/scripts: not found\n";
		NormalPrint "kernel-source or kernel-devel is required to build $srpm\n";
		return 1;	# failure
	}
	return 0;
}

# see if basic prereqs for building RPMs are installed
# return 0 on success, or number of missing dependencies
sub check_rpmbuild_dependencies($)
{
	my $srpm = shift();	# what trying to build
	my $err = 0;

	if ("$CUR_DISTRO_VENDOR" eq 'redhat') {
		if (! rpm_is_installed("rpm-build", "any") ) {
			NormalPrint("rpm-build ($last_checked) is required to build $srpm\n");
			$err++;
		}
		# RHEL 8 and later
		if (substr("$CUR_VENDOR_VER", 0, 3) eq "ES8") {
			if (! rpm_is_installed("kernel-rpm-macros", "any") ) {
				NormalPrint("kernel-rpm-macros ($last_checked) is required to build $srpm\n");
				$err++;
			}
			if (! rpm_is_installed("kernel-abi-whitelists", "any") && ! rpm_is_installed("kernel-abi-stablelists", "any") ) {
				NormalPrint("kernel-abi-whitelists or kernel-abi-stablelists ($last_checked) is required to build $srpm\n");
				$err++;
			}
		}
	}
	if ( "$CUR_DISTRO_VENDOR" ne "SuSE" && rpm_will_build_debuginfo()) {
		if (! rpm_is_installed("redhat-rpm-config", "any")) {
			NormalPrint("redhat-rpm-config ($last_checked) is required to build $srpm\n");
			$err++;
		}
	}
	return $err;
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# =============================================================================
# The functions and constants below assist in doing builds such as via rpmbuild

# The functions below assume a hash of build options.  A sample is shown below
#my %ofed_kernel_ib_options = (
#	# build option		# arch & kernels supported on
#	"--with-core-mod" => "",	# supported on all
#	"--with-ehca-mod" => "PPC 2\.6\.1[6-9].* 2\.6\.20.* 2\.6\.9-55\.
#							PPC64 2\.6\.1[6-9].* 2\.6\.20.* 2\.6\.9-55\.",
#	"--with-iser-mod" => "ALL 2\.6\.16\..*-.*-.* 2\.6\..*\.el5 2\.6\.9-[3-5].*\.EL.*",
#		# all kernels except 2.6.5*  note .* wildcard need as 2nd kernelpat
#	"--with-rds-mod" => "ALL !2\.6\.5.* .*",
#	"--without-ipoibconf" => "NONE",	# essentially a comment
#			# DAPL not supported for PPC64
#	"--with-dapl" => "!PPC64",	# any kernel for !PPC64
#);

# The arch & kernels specification is quite flexible.
#
# special formats:
# 		"" -> always use option (any arch, any kernels)
# 		"NONE" -> never use option, no remaining lines are processed
#
# typical format is one line per arch, separated by newline (inside string):
# 		"arch1 kernelpat1 kernelpat2
#			arch2 kernelpat3"
# leading spaces and tabs ignored before arch
#
# arch format:
#	exact ARCH value (IA32, PPC, X86_64, etc)
#	ALL - remainder of line applies to all architectures
#			if no matches for kernel are found on this line, continues to later
#			lines
#	!arch - remainder of line applies to all architectures except arch
#			if no matches for kernel are found on this line, continues to later
#			lines.  If no kernels listed, applies to any kernel.
#	if for a given arch line, no kernels are specified, it matches any kernels
#
# kernelpat format:
#	"" -> (eg. no kernelpat specified for arch), option applies to any kernel
#			for given arch
#	 - all patterns are regex style
#		beware: . is a wildcard unless \. used
#	- !kernelpat means not on kernel, unlike !arch this indicates option is
#		not appliable to this specific kernel, but does not affect other kernels

# process osver and $ARCH against the list of allowed kernel/arch for
# a given build option to decide if option allowed for given kernel/arch
sub arch_kernel_is_allowed($$)
{
	my $osver = shift();
	my $archs = shift();

	if ( "$archs" eq "" ) {
		# option applicable to all archs all kernels
		DebugPrint "yes\n";
		return 1;
	} else {
		# newlines separate details of each arch
		my @arch_list = split /\n/, $archs;
		foreach my $archdetails ( @arch_list ) {
			# spaces separate arch and each kernelpattern
			# ignore leading and trailing tabs/spaces
			$archdetails =~ s/^[ 	]*//;	# remove leading
			$archdetails =~ s/[ 	]*$//;	# remove trailing
			# all other whitespace is just separators
			my @archkernels = split /[[:space:]]+/,$archdetails;
			# arch is 1st, rest are kernelpatterns
			my $arch = $archkernels[0];
			shift @archkernels;
			if ( "$arch" eq "NONE" ) {
				DebugPrint "no\n";
				return 0;
			} elsif ( "$ARCH" eq "$arch" || "ALL" eq "$arch"
				|| (substr($arch,0,1) eq "!" && "$ARCH" ne substr($arch,1)) ) {
				if (scalar(@archkernels) == 0) {
					# option applicable to all kernels for arch
					DebugPrint "yes\n";;
					return 1;
				} else {
					# list of kernel patterns specified
					foreach my $kernelpattern ( @archkernels ) {
#print "check $kernelpattern\n";
						if (substr($kernelpattern,0,1) eq "!") {
							$kernelpattern = substr($kernelpattern, 1);
							if ( $osver =~ /^$kernelpattern$/ ) {
								# option not available on this kernel
								DebugPrint "no\n";
								return 0;
							}
						} elsif ( $osver =~ /^$kernelpattern$/ ) {
							# option applicable to this kernel for arch
							DebugPrint "yes\n";
							return 1;
						}
					}
				}
			}
		}
	}
	DebugPrint "no\n";
	return 0;	# not specified
}

# given a build option and a kernel, decide if applicable to ARCH and kernel
# based on lookup in build_options hash
sub build_option_is_allowed($$@)
{
	my $osver = shift();
	my $build_option = shift();
	my(%build_options) = @_;	# list of options and when valid

	return arch_kernel_is_allowed($osver, $build_options{$build_option});
}

# based on $osver and $ARCH decide what build options to use
sub get_build_options($@)
{
	my $osver = shift();
	my(@build_options) = @_;	# list of options and when valid

	my $ret = "";
	my $i;
	for($i=0; $i < scalar(@build_options); $i += 2) {
		my $option = $build_options[$i];
		my $archs = $build_options[$i+1];
		if (arch_kernel_is_allowed($osver, $archs)) {
			DebugPrint "Check $option - yes\n";
			$ret="$ret $option";
		} else {
			DebugPrint "Check $option - no\n";
		}
	}
	return "$ret";
}

# execute build_cmd within srcdir
# return 0 on success, != 0 on failure
sub run_build($$$$)
{
	my $message= shift();	# message for building output
	my $srcdir= shift();
	my $build_cmd= shift();
	my $resfileop= shift();	# "append" or "replace"

	my $rc;
	my $shfileop;
	
	if ( "$resfileop" eq "append" ) {
		$shfileop = ">>";
	} else {
		$shfileop = ">";
	}

	NormalPrint "Building $message...";

	LogPrint "\n  cd $srcdir; $build_cmd $shfileop build.res 2>&1\n";
	$rc=system "cd $srcdir; $build_cmd $shfileop build.res 2>&1";
	if ( $rc != 0 ) {
		NormalPrint "\nERROR - FAILED to build $message, see $srcdir/build.res\n";
		# TBD system("cat $srcdir/build.res >> $LogFile");
	} else {
		NormalPrint " done\n";
	}
	return $rc;
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;

my $Default_FirmwareUpgradeMode="";	# --fwupdate option
#  "" - normal operation for upgrade
#  "asneeded" - force update to this rev unless already on HCA
#  "always" - force update to this rev
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

#[ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
use File::Basename;

#############################################################################
##
##    MPI installation generic functions

# these functions can be used by the MPI specific install functions

# installs PSM based MPI component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_generic_mpi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];
    my $mpiname = $_[2];
    my $compiler = $_[3];
    my $suffix = $_[4];
    my $mpifullname = "$mpiname"."_$compiler";
    if ( "$suffix" ne "") {
        $mpifullname = "$mpifullname" . "_" . "$suffix";
    }
    my $srcdir = $ComponentInfo{$mpifullname}{'SrcDir'};
    my $version = eval "media_version_$mpifullname()";
    
    printf ("Installing $ComponentInfo{$mpifullname}{'Name'} $version...\n");
    LogPrint ("Installing $ComponentInfo{$mpifullname}{'Name'} $version for $CUR_OS_VER\n");
    # make sure any old potentially custom built versions of mpi are uninstalled
    uninstall_comp_rpms($mpifullname, ' --nodeps ', $install_list, $installing_list, 'silent');
	# cleanup from older installs just in case
    system ("rm -rf /usr/lib/opa/.comp_$mpifullname.pl");
    
    my $rpmfile = rpm_resolve("$srcdir/$mpifullname", "any");
    if ( "$rpmfile" ne "" && -e "$rpmfile" ) {
	my $mpich_prefix= "/usr/mpi/$compiler/$mpiname-"
	    . rpm_query_attr($rpmfile, "VERSION");
    if ( "$suffix" ne "") {
        $mpich_prefix= "$mpich_prefix" . "-" . "$suffix";
    }
	if ( -d "$mpich_prefix" ) {
	    if (GetYesNo ("Remove $mpich_prefix directory?", "y")) {
		LogPrint "rm -rf $mpich_prefix\n";
		system("rm -rf $mpich_prefix");
	    }
	}
    }
    # enable this code if mpitests is missing for some compilers or MPIs
    #my $mpitests_rpmfile = rpm_resolve("$srcdir/OtherMPIs/mpitests_$mpifullname", "any");
    #if ( "$mpitests_rpmfile" ne "" && -e "$mpitests_rpmfile" ) {
        install_comp_rpms($mpifullname, " -U --nodeps ", $install_list);
    #} else {
    #    rpm_install("$srcdir/OtherMPIs/$mpifullname", "user");
    #}

    $ComponentWasInstalled{$mpifullname} = 1;
}

sub installed_generic_mpi
{
    my $mpiname = $_[0];
    my $compiler = $_[1];
    my $suffix = $_[2];
    my $mpifullname = "$mpiname"."_$compiler";
    if ( "$suffix" ne "") {
        $mpifullname = "$mpifullname" . "_" . "$suffix";
    }

    return (rpm_is_installed ($mpifullname, "user") );
}

sub uninstall_generic_mpi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];
    my $mpiname = $_[2];
    my $compiler = $_[3];
    my $suffix = $_[4];
    my $mpifullname = "$mpiname"."_$compiler";
    if ( "$suffix" ne "") {
        $mpifullname = "$mpifullname" . "_" . "$suffix";
    }
    my $mpich_prefix= "/usr/mpi/$compiler/$mpiname-"
        . rpm_query_attr_pkg("$mpifullname", "VERSION");
    if ( "$suffix" ne "") {
        $mpich_prefix= "$mpich_prefix" . "-" . "$suffix";
    }
    my $rc;
    my $top;
    
    NormalPrint ("Uninstalling $ComponentInfo{$mpifullname}{'Name'}...\n");
	$top = rpm_query_attr_pkg("$mpifullname", "INSTALLPREFIX");
    if ($top eq "" || $top =~ /is not installed/) {
		$top = undef;
    } else {
		$top = `dirname $top`;
		chomp $top;
    }
    
    # uninstall tests in case built by do_build
    uninstall_comp_rpms($mpifullname, '', $install_list, $installing_list, 'verbose');

	# unfortunately mpi and mpitests can leave empty directories on uninstall
	# this can confuse IFS MPI tools because correct MPI to use
	# cannot be identified.  This remove such empty directories
	if ( -d "/$mpich_prefix" ) {
		system("cd '/$mpich_prefix'; rmdir -p tests/* >/dev/null 2>&1");
	}
    if ( -d $top ) {
		my @files = glob("$top/*");
		my $num = scalar (@files);
		if ( $num == 0 ) {
			system ("rm -rf $top");
		}
    }
    
	# cleanup from older installs just in case
    system ("rm -rf /usr/lib/opa/.comp_$mpifullname.pl");
    system ("rmdir /usr/lib/opa 2>/dev/null"); # remove only if empty
    $ComponentWasInstalled{$mpifullname} = 0;
}

#############################################################################
##
##    OpenMPI GCC Verbs

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)
sub get_rpms_dir_openmpi_gcc
{
    return $ComponentInfo{'openmpi_gcc'}{'SrcDir'};
}

sub available_openmpi_gcc
{
    my $srcdir = $ComponentInfo{'openmpi_gcc'}{'SrcDir'};
    return rpm_exists ("$srcdir/openmpi_gcc", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_openmpi_gcc
{
    return  installed_generic_mpi("openmpi", "gcc", "");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_openmpi_gcc
{
    return rpm_query_version_release_pkg ("openmpi_gcc");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_openmpi_gcc
{
    my $srcdir = $ComponentInfo{'openmpi_gcc'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/openmpi_gcc", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_openmpi_gcc
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_openmpi_gcc
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_openmpi_gcc
{
	return rpm_check_os_prereqs("openmpi_gcc", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_openmpi_gcc
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_openmpi_gcc
{
    install_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", "");
}

# called after all components are installed.
sub postinstall_openmpi_gcc
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_openmpi_gcc
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", "");
}

#############################################################################
##
##    MVAPICH2 GCC Verbs

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_mvapich2_gcc
{
    return $ComponentInfo{'mvapich2_gcc'}{'SrcDir'};
}

sub available_mvapich2_gcc
{
    my $srcdir = $ComponentInfo{'mvapich2_gcc'}{'SrcDir'};
    return rpm_exists ("$srcdir/mvapich2_gcc", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_mvapich2_gcc
{
    return  installed_generic_mpi("mvapich2", "gcc", "");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_mvapich2_gcc
{
    return rpm_query_version_release_pkg ("mvapich2_gcc");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_mvapich2_gcc
{
    my $srcdir = $ComponentInfo{'mvapich2_gcc'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/mvapich2_gcc", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_mvapich2_gcc
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_mvapich2_gcc
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_mvapich2_gcc
{
	return rpm_check_os_prereqs("mvapich2_gcc", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_mvapich2_gcc
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_mvapich2_gcc
{
	install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", "");
}

# called after all components are installed.
sub postinstall_mvapich2_gcc
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_mvapich2_gcc
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", "");
}

#############################################################################
##
##    OpenMPI GCC PSM

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_openmpi_gcc_hfi
{
    return $ComponentInfo{'openmpi_gcc_hfi'}{'SrcDir'};
}

sub available_openmpi_gcc_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_gcc_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/openmpi_gcc_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_openmpi_gcc_hfi
{
    return  installed_generic_mpi("openmpi", "gcc", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_openmpi_gcc_hfi
{
    return rpm_query_version_release_pkg ("openmpi_gcc_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_openmpi_gcc_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_gcc_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/openmpi_gcc_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_openmpi_gcc_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_openmpi_gcc_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_openmpi_gcc_hfi
{
	return rpm_check_os_prereqs("openmpi_gcc_hfi", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_openmpi_gcc_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_openmpi_gcc_hfi
{
    install_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", "hfi");
}

# called after all components are installed.
sub postinstall_openmpi_gcc_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_openmpi_gcc_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", "hfi");
}

#############################################################################
##
##    OpenMPI Intel PSM

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_openmpi_intel_hfi
{
    return $ComponentInfo{'openmpi_intel_hfi'}{'SrcDir'};
}

sub available_openmpi_intel_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_intel_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/openmpi_intel_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_openmpi_intel_hfi
{
    return  installed_generic_mpi("openmpi", "intel", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_openmpi_intel_hfi
{
    return rpm_query_version_release_pkg ("openmpi_intel_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_openmpi_intel_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_intel_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/openmpi_intel_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_openmpi_intel_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_openmpi_intel_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_openmpi_intel_hfi
{
	return rpm_check_os_prereqs("openmpi_intel_hfi", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_openmpi_intel_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_openmpi_intel_hfi
{
    install_generic_mpi("$_[0]", "$_[1]", "openmpi", "intel", "hfi");
}

# called after all components are installed.
sub postinstall_openmpi_intel_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_openmpi_intel_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "intel", "hfi");
}

#############################################################################
##
##    OpenMPI PGI PSM

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_openmpi_pgi_hfi
{
    return $ComponentInfo{'openmpi_pgi_hfi'}{'SrcDir'};
}

sub available_openmpi_pgi_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_pgi_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/openmpi_pgi_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_openmpi_pgi_hfi
{
    return  installed_generic_mpi("openmpi", "pgi", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_openmpi_pgi_hfi
{
    return rpm_query_version_release_pkg ("openmpi_pgi_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_openmpi_pgi_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_pgi_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/openmpi_pgi_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_openmpi_pgi_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_openmpi_pgi_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_openmpi_pgi_hfi
{
	return rpm_check_os_prereqs("openmpi_pgi_hfi", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_openmpi_pgi_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_openmpi_pgi_hfi
{
	install_generic_mpi("$_[0]", "$_[1]", "openmpi", "pgi", "hfi");
}

# called after all components are installed.
sub postinstall_openmpi_pgi_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_openmpi_pgi_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "pgi", "hfi");
}

#############################################################################
##
##    MVAPICH2 GCC PSM

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_mvapich2_gcc_hfi
{
    return $ComponentInfo{'mvapich2_gcc_hfi'}{'SrcDir'};
}

sub available_mvapich2_gcc_hfi
{
    my $srcdir = $ComponentInfo{'mvapich2_gcc_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/mvapich2_gcc_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_mvapich2_gcc_hfi
{
    return  installed_generic_mpi("mvapich2", "gcc", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_mvapich2_gcc_hfi
{
    return rpm_query_version_release_pkg ("mvapich2_gcc_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_mvapich2_gcc_hfi
{
    my $srcdir = $ComponentInfo{'mvapich2_gcc_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/mvapich2_gcc_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_mvapich2_gcc_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_mvapich2_gcc_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_mvapich2_gcc_hfi
{
	return rpm_check_os_prereqs("mvapich2_gcc_hfi", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_mvapich2_gcc_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_mvapich2_gcc_hfi
{
	install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", "hfi");
}

# called after all components are installed.
sub postinstall_mvapich2_gcc_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_mvapich2_gcc_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", "hfi");
}

#############################################################################
##
##    MVAPICH2 Intel PSM

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_mvapich2_intel_hfi
{
    return $ComponentInfo{'mvapich2_intel_hfi'}{'SrcDir'};
}

sub available_mvapich2_intel_hfi
{
    my $srcdir = $ComponentInfo{'mvapich2_intel_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/mvapich2_intel_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_mvapich2_intel_hfi
{
    return  installed_generic_mpi("mvapich2", "intel", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_mvapich2_intel_hfi
{
    return rpm_query_version_release_pkg ("mvapich2_intel_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_mvapich2_intel_hfi
{
    my $srcdir = $ComponentInfo{'mvapich2_intel_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/mvapich2_intel_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_mvapich2_intel_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_mvapich2_intel_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_mvapich2_intel_hfi
{
	# we allow this to install even if intel compiler runtime not available
	return rpm_check_os_prereqs("mvapich2_intel_hfi", "user");
}                              

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_mvapich2_intel_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_mvapich2_intel_hfi
{
	install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "intel", "hfi");
}

# called after all components are installed.
sub postinstall_mvapich2_intel_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_mvapich2_intel_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "intel", "hfi");
}

#############################################################################
##
##    MVAPICH2 PGI PSM

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_mvapich2_pgi_hfi
{
    return $ComponentInfo{'mvapich2_pgi_hfi'}{'SrcDir'};
}

sub available_mvapich2_pgi_hfi
{
    my $srcdir = $ComponentInfo{'mvapich2_pgi_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/mvapich2_pgi_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_mvapich2_pgi_hfi
{
    return  installed_generic_mpi("mvapich2", "pgi", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_mvapich2_pgi_hfi
{
    return rpm_query_version_release_pkg ("mvapich2_pgi_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_mvapich2_pgi_hfi
{
    my $srcdir = $ComponentInfo{'mvapich2_pgi_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/mvapich2_pgi_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_mvapich2_pgi_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_mvapich2_pgi_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_mvapich2_pgi_hfi
{
	# we allow this to install even if pgi compiler runtime not available
	return rpm_check_os_prereqs("mvapich2_pgi_hfi", "user");
}                              

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_mvapich2_pgi_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_mvapich2_pgi_hfi
{
	install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "pgi", "hfi");
}

# called after all components are installed.
sub postinstall_mvapich2_pgi_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_mvapich2_pgi_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "pgi", "hfi");
}



#############################################################################
###
###    OpenMPI GCC CUDA
#

# is component X available on the install media (use of this
# allows for optional components in packaging or limited availability if a
# component isn't available on some OS/CPU combos)

sub get_rpms_dir_openmpi_gcc_cuda_hfi
{
    return $ComponentInfo{'openmpi_gcc_cuda_hfi'}{'SrcDir'};
}

sub available_openmpi_gcc_cuda_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_gcc_cuda_hfi'}{'SrcDir'};
    return rpm_exists ("$srcdir/openmpi_gcc_cuda_hfi", "user");
}

# is component X presently installed on the system.  This is
# a quick check, not a "verify"
sub installed_openmpi_gcc_cuda_hfi
{
    return  installed_generic_mpi("openmpi", "gcc_cuda", "hfi");
}

# what is the version installed on system.  Only
# called if installed_X is true.  versions are short strings displayed and
# logged, no operations are done (eg. only compare for equality)
sub installed_version_openmpi_gcc_cuda_hfi
{
    return rpm_query_version_release_pkg ("openmpi_gcc_cuda_hfi");
}

# only called if available_X.  Indicates version on
# media.  Will be compared with installed_version_X to determine if
# present installation is up to date.  Should return exact same format for
# version string so comparison of equality is possible.
sub media_version_openmpi_gcc_cuda_hfi
{
    my $srcdir = $ComponentInfo{'openmpi_gcc_cuda_hfi'}{'SrcDir'};
    my $rpm = rpm_resolve ("$srcdir/openmpi_gcc_cuda_hfi", "user");
    return rpm_query_version_release ($rpm);
}

# used to build/rebuild component on local system (if
# supported).  We support this for many items in comp_ofed.pl
# Other components (like SM) are
# not available in source and hence do not support this and simply
# implement a noop.
sub build_openmpi_gcc_cuda_hfi
{
    my $osver = $_[0];
    my $debug = $_[1];
    my $build_temp = $_[2];
    my $force = $_[3];

    return 0;
}

# does this need to be reinstalled.  Mainly used for
# ofed due to subtle changes such as install prefix or kernel options
# which may force a reinstall.  You'll find this is a noop in most others.
sub need_reinstall_openmpi_gcc_cuda_hfi
{
    my $install_list = shift ();
    my $installing_list = shift ();

    return "no";
}

# called for all components before they are installed.  Use to verify OS
# has proper dependent rpms installed.
sub check_os_prereqs_openmpi_gcc_cuda_hfi
{
       return rpm_check_os_prereqs("openmpi_gcc_cuda_hfi", "user");
}

# called for all components before they are installed.  Use
# to build things if needed, etc.
sub preinstall_openmpi_gcc_cuda_hfi
{
    my $install_list = $_[0];
    my $installing_list = $_[1];

    my $full = "";
    my $rc;

    return 0;
}

# installs component.  also handles reinstall on top of
# existing installation and upgrade.
sub install_openmpi_gcc_cuda_hfi
{
    install_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc_cuda", "hfi");
}

# called after all components are installed.
sub postinstall_openmpi_gcc_cuda_hfi
{
    my $install_list = $_[0];     # total that will be installed when done
    my $installing_list = $_[1];  # what items are being installed/reinstalled
}

# uninstalls component.  May be called even if component is
# partially or not installed at all in which case should do its best to
# get rid or what might remain of component from a previously aborted
# uninstall or failed install
sub uninstall_openmpi_gcc_cuda_hfi
{
    uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc_cuda", "hfi");
}

#############################################################################
###
###    MPI Source

sub available_mpisrc()
{
	my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'};
	return has_mpisrc($srcdir);
	#return ( (-d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ) );
}

sub installed_mpisrc()
{
	my $srcdir = $ExtraMpisrcInfo{'Dest'};
	my $old_srcdir = "/usr/lib/opa/src/MPI";
	return (has_mpisrc($srcdir) || has_mpisrc($old_srcdir));
}

sub has_mpisrc($)
{
	my $srcdir = shift();
	foreach my $srpm (@{$ExtraMpisrcInfo{'SrcRpms'}}) {
		if (file_glob("$srcdir/${srpm}*.src.rpm") eq "") {
			return 0;
		}
	}
	return 1;
}

# only called if installed_mpisrc is true
sub installed_version_mpisrc()
{
	return `cat $ExtraMpisrcInfo{'Dest'}/.version`;
}

# only called if available_mpisrc is true
sub media_version_mpisrc()
{
	my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'};
	return `cat "$srcdir/version"`;
}

sub build_mpisrc($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild
	return 0;	# success
}

sub need_reinstall_mpisrc($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

    return "no";
}

sub check_os_prereqs_mpisrc
{
	return rpm_check_os_prereqs("mpisrc", "any");
}

sub preinstall_mpisrc($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

    return 0;
}

sub install_mpisrc($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'};
	my $version = media_version_mpisrc();
	chomp $version;

	printf ("Installing $ComponentInfo{'mpisrc'}{'Name'} $version...\n");
	LogPrint ("Installing $ComponentInfo{'mpisrc'}{'Name'} $version for $CUR_OS_VER\n");

	my $destdir = $ExtraMpisrcInfo{'Dest'};
	check_dir($destdir);
	# remove old versions (.src.rpm and built .rpm files too)
	system "rm -f $destdir/mvapich[-_]*.rpm 2>/dev/null";
	foreach my $srpm (@{$ExtraMpisrcInfo{'SrcRpms'}})
	{
		system "rm -f $destdir/$srpm-*.rpm 2>/dev/null";
	}
	foreach my $file (@{$ExtraMpisrcInfo{'DirtyFiles'}})
	{
		system "rm -f $destdir/$file 2>/dev/null";
	}

	# install new versions
	foreach my $srpm (@{$ExtraMpisrcInfo{'SrcRpms'}}) {
		my $srpmfile = file_glob("$srcdir/${srpm}-*.src.rpm");
		if ( "$srpmfile" ne "" ) {
			my $file = my_basename($srpmfile);
			copy_data_file($srpmfile, "$destdir/$file");
		}
	}
	foreach my $script (@{$ExtraMpisrcInfo{'BuildScripts'}}) {
		copy_systool_file("$srcdir/$script", "$destdir/$script");
	}
	foreach my $file (@{$ExtraMpisrcInfo{'MiscFiles'}}) {
		my $src = ${$file}{'Src'};
		my $dest = ${$file}{'Dest'};
		copy_data_file("$srcdir/$src", "$destdir/$dest");
	}

	$ComponentWasInstalled{'mpisrc'}=1;
}

sub postinstall_mpisrc($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled
}

sub uninstall_mpisrc($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	NormalPrint ("Uninstalling $ComponentInfo{'mpisrc'}{'Name'}...\n");

	# try to uninstall meta pkg if it exists
	if (rpm_is_installed("opameta_mpisrc", "any") ||
	    rpm_is_installed("opameta_mpisrc_userspace", "any")) {
		rpm_uninstall_matches("opameta_mpisrc", "opameta_mpisrc", "", "");
	} else {
		my $destdir = $ExtraMpisrcInfo{'Dest'};
		# remove old versions (.src.rpm and built .rpm files too)
		foreach my $srpm (@{$ExtraMpisrcInfo{'SrcRpms'}}) {
			system "rm -f $destdir/$srpm-*.rpm 2>/dev/null";
		}
		foreach my $script (@{$ExtraMpisrcInfo{'BuildScripts'}}) {
			system "rm -f $destdir/$script 2>/dev/null";
		}
		foreach my $file (@{$ExtraMpisrcInfo{'MiscFiles'}}) {
			my $destfile = ${$file}{'Dest'};
			system "rm -f $destdir/$destfile 2>/dev/null";
		}
		foreach my $file (@{$ExtraMpisrcInfo{'DirtyFiles'}}) {
			system "rm -f $destdir/$file 2>/dev/null";
		}

		system "rmdir $destdir 2>/dev/null"; # remove only if empty
		system "rmdir /usr/src/opa 2>/dev/null"; # remove only if empty
	}

	$ComponentWasInstalled{'mpisrc'}=0;
}
#!/usr/bin/perl
## BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
# Copyright (c) 2020, Cornelis Networks, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
## END_ICS_COPYRIGHT8   ****************************************
#
## [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
#use strict;
##use Term::ANSIColor;
##use Term::ANSIColor qw(:constants);
##use File::Basename;
##use Math::BigInt;
#
## ==========================================================================
#
#Installation Prequisites array for fast fabric
#and of tools component
my @oftools_prereq = (
    "glibc",
    "libgcc",
    "libibumad",
    "libibverbs",
    "libstdc++",
    "ibacm",
    "rdma-core",
);
$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq;

my @fastfabric_prereq = (
    "atlas",
    "bash",
    "bc",
    "expat",
    "expect",
    "glibc",
    "libgcc",
    "libibumad",
    "libibverbs",
    "libstdc++",
    "ncurses-libs",
    "openssl-libs",
    "perl",
    "perl-Getopt-Long",
    "perl-Socket",
    "rdma-core",
    "tcl",
    "zlib",
);
$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq;

my @opamgt_sdk_prereq = (
    "bash",
    "glibc",
    "libgcc",
    "libibumad",
    "libibverbs",
    "libstdc++",
    "openssl",
    "openssl-devel",
    "openssl-libs",
    "rdma-core-devel",
);
$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq;
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ==========================================================================
# Fast Fabric Support tools for OFA (oftools) installation

sub get_rpms_dir_oftools
{
	my $srcdir=$ComponentInfo{'oftools'}{'SrcDir'};
	return "$srcdir/RPMS/*";
}

sub available_oftools
{
# TBD - could we move the algorithms for many of these functions into
# util_component.pl and simply put a list of rpms in the ComponentInfo
# as well as perhaps config files
	my $srcdir=$ComponentInfo{'oftools'}{'SrcDir'};
	return ((rpm_resolve("$srcdir/RPMS/*/opa-basic-tools", "any") ne "")
			&& (rpm_resolve("$srcdir/RPMS/*/opa-address-resolution", "any") ne "" ));
}

sub installed_oftools
{
	return rpm_is_installed("opa-basic-tools", "any");
}

# only called if installed_oftools is true
sub installed_version_oftools
{
	my $version = rpm_query_version_release_pkg("opa-basic-tools");
	return dot_version("$version");
}

# only called if available_oftools is true
sub media_version_oftools
{
	my $srcdir=$ComponentInfo{'oftools'}{'SrcDir'};
	my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opa-basic-tools", "any");
	my $version= rpm_query_version_release("$rpmfile");
	# assume media properly built with matching versions for all rpms
	return dot_version("$version");
}

sub build_oftools
{
	my $osver = $_[0];
	my $debug = $_[1];	# enable extra debug of build itself
	my $build_temp = $_[2];	# temp area for use by build
	my $force = $_[3];	# force a rebuild
	return 0;	# success
}

sub need_reinstall_oftools($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return "no";
}

sub preinstall_oftools
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled

	return 0;	# success
}

sub install_oftools
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled

	my $version=media_version_oftools();
	chomp $version;
	printf("Installing $ComponentInfo{'oftools'}{'Name'} $version $DBG_FREE...\n");
	# TBD - review all components and make installing messages the same
	#LogPrint "Installing $ComponentInfo{'oftools'}{'Name'} $version $DBG_FREE for $CUR_OS_VER\n";
	LogPrint "Installing $ComponentInfo{'oftools'}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER\n";

	# RHEL7.4 and older in-distro IFS defines opa-address-resolution depends on opa-basic-tools with exact version match
	# that will fail our installation because of dependency check. We need to use '-nodeps' to force the installation
	install_comp_rpms('oftools', " -U --nodeps ", $install_list);

# TBD - could we figure out the list of config files from a query of rpm
# and then simply iterate on each config file?
	check_rpm_config_file("/etc/rdma/dsap.conf");

	$ComponentWasInstalled{'oftools'}=1;
}

sub postinstall_oftools
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled
}

sub uninstall_oftools
{
	my $install_list = $_[0];	# total that will be left installed when done
	my $uninstalling_list = $_[1];	# what items are being uninstalled

	NormalPrint("Uninstalling $ComponentInfo{'oftools'}{'Name'}...\n");

	uninstall_comp_rpms('oftools', '', $install_list, $uninstalling_list, 'verbose');

	# remove LSF and Moab related files
	system("rm -rf /usr/lib/opa/LSF_scripts");
	system("rm -rf /usr/lib/opa/Moab_scripts");

	# may be created by opaverifyhosts
	system("rm -rf /usr/lib/opa/tools/nodescript.sh");
	system("rm -rf /usr/lib/opa/tools/nodeverify.sh");

	system "rmdir /usr/lib/opa/tools 2>/dev/null";	# remove only if empty

	# oftools is a prereq of fastfabric can cleanup shared files here
	system("rm -rf $BASE_DIR/version_ff");
	system "rmdir $BASE_DIR 2>/dev/null";	# remove only if empty
	system "rmdir $OPA_CONFIG_DIR 2>/dev/null";	# remove only if empty
	system("rm -rf /usr/lib/opa/.comp_oftools.pl");
	system "rmdir /usr/lib/opa 2>/dev/null";	# remove only if empty
	$ComponentWasInstalled{'oftools'}=0;
}

sub check_os_prereqs_oftools
{
	return rpm_check_os_prereqs("oftools", "user");
}
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ==========================================================================
# Fast Fabric installation

my $FF_CONF_FILE = "/usr/lib/opa/tools/opafastfabric.conf";
my $FF_TLS_CONF_FILE = "/etc/opa/opaff.xml";

sub get_rpms_dir_fastfabric
{
	my $srcdir=$ComponentInfo{'fastfabric'}{'SrcDir'};
	return "$srcdir/RPMS/*";
}

sub available_fastfabric
{
	my $srcdir=$ComponentInfo{'fastfabric'}{'SrcDir'};
	return ((rpm_resolve("$srcdir/RPMS/*/opa-mpi-apps", "any") ne "") &&
			(rpm_resolve("$srcdir/RPMS/*/opa-fastfabric", "any") ne ""));
}

sub installed_fastfabric
{
	return rpm_is_installed("opa-fastfabric", "any");
}

# only called if installed_fastfabric is true
sub installed_version_fastfabric
{
	my $version = rpm_query_version_release_pkg("opa-fastfabric");
	return dot_version("$version");
}

# only called if available_fastfabric is true
sub media_version_fastfabric
{
	my $srcdir=$ComponentInfo{'fastfabric'}{'SrcDir'};
	my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opa-fastfabric", "any");
	my $version= rpm_query_version_release("$rpmfile");
	# assume media properly built with matching versions for all rpms
	return dot_version("$version");
}

sub build_fastfabric
{
	my $osver = $_[0];
	my $debug = $_[1];	# enable extra debug of build itself
	my $build_temp = $_[2];	# temp area for use by build
	my $force = $_[3];	# force a rebuild
	return 0;	# success
}

sub need_reinstall_fastfabric($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return "no";
}

sub check_os_prereqs_fastfabric
{	
	return rpm_check_os_prereqs("fastfabric", "user");
}

sub preinstall_fastfabric
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled

	return 0;	# success
}

sub install_fastfabric
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled

	my $depricated_dir = "/etc/sysconfig/opa";

	my $version=media_version_fastfabric();
	chomp $version;
	printf("Installing $ComponentInfo{'fastfabric'}{'Name'} $version $DBG_FREE...\n");
	LogPrint "Installing $ComponentInfo{'fastfabric'}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER\n";

	install_comp_rpms('fastfabric', " -U ", $install_list);

	# TBD - spec file should do this
	check_dir("/usr/share/opa/samples");
	system "chmod ug+x /usr/share/opa/samples/hostverify.sh";
	system "rm -f /usr/share/opa/samples/nodeverify.sh";

	check_rpm_config_file("$FF_TLS_CONF_FILE");
	printf("Default opaff.xml can be found in '/usr/share/opa/samples/opaff.xml-sample'\n");
	check_rpm_config_file("$CONFIG_DIR/opa/opamon.conf", $depricated_dir);
	check_rpm_config_file("$CONFIG_DIR/opa/opafastfabric.conf", $depricated_dir);
	check_rpm_config_file("$CONFIG_DIR/opa/allhosts", $depricated_dir);
	check_rpm_config_file("$CONFIG_DIR/opa/chassis", $depricated_dir);
	check_rpm_config_file("$CONFIG_DIR/opa/hosts", $depricated_dir);
	check_rpm_config_file("$CONFIG_DIR/opa/ports", $depricated_dir);
	check_rpm_config_file("$CONFIG_DIR/opa/switches", $depricated_dir);
# TBD - this should not be a config file
	check_rpm_config_file("/usr/lib/opa/tools/osid_wrapper");

	# TBD - spec file should remove this
	system("rm -rf $OPA_CONFIG_DIR/iba_stat.conf");	# old config

	$ComponentWasInstalled{'fastfabric'}=1;
}

sub postinstall_fastfabric
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled
}

sub uninstall_fastfabric
{
	my $install_list = $_[0];	# total that will be left installed when done
	my $uninstalling_list = $_[1];	# what items are being uninstalled

	uninstall_comp_rpms('fastfabric', '', $install_list, $uninstalling_list, 'verbose');

	NormalPrint("Uninstalling $ComponentInfo{'fastfabric'}{'Name'}...\n");
	remove_conf_file("$ComponentInfo{'fastfabric'}{'Name'}", "$FF_CONF_FILE");
	remove_conf_file("$ComponentInfo{'fastfabric'}{'Name'}", "$OPA_CONFIG_DIR/iba_stat.conf");
	remove_conf_file("$ComponentInfo{'fastfabric'}{'Name'}", "$FF_TLS_CONF_FILE");
	
	# remove samples we installed (or user compiled), however do not remove
	# any logs or other files the user may have created
	remove_installed_files "/usr/share/opa/samples";
	system "rmdir /usr/share/opa/samples 2>/dev/null";	# remove only if empty
	# just in case, newer rpms should clean these up

	system("rm -rf /usr/lib/opa/.comp_fastfabric.pl");
	system "rmdir /usr/lib/opa 2>/dev/null";	# remove only if empty
	system "rmdir $BASE_DIR 2>/dev/null";	# remove only if empty
	system "rmdir $OPA_CONFIG_DIR 2>/dev/null";	# remove only if empty
	$ComponentWasInstalled{'fastfabric'}=0;
}

#############################################################################
##
##    OPAMGT SDK

sub get_rpms_dir_opamgt_sdk
{
	my $srcdir=$ComponentInfo{'opamgt_sdk'}{'SrcDir'};
	return "$srcdir/RPMS/*";
}

sub available_opamgt_sdk
{
	my $srcdir = $ComponentInfo{'opamgt_sdk'}{'SrcDir'};
	return ( rpm_exists("$srcdir/RPMS/*/opa-libopamgt-devel", "any") &&
		     rpm_exists("$srcdir/RPMS/*/opa-libopamgt", "any"));
}

sub installed_opamgt_sdk
{
	return ( rpm_is_installed("opa-libopamgt-devel", "any") &&
		     rpm_is_installed("opa-libopamgt", "any"));
}

sub installed_version_opamgt_sdk
{
	my $version = rpm_query_version_release_pkg("opa-libopamgt-devel");
	return dot_version("$version");
}

sub media_version_opamgt_sdk
{
	my $srcdir = $ComponentInfo{'opamgt_sdk'}{'SrcDir'};
	my $rpm = rpm_resolve("$srcdir/RPMS/*/opa-libopamgt-devel", "any");
	my $version = rpm_query_version_release($rpm);
	return dot_version("$version");
}

sub build_opamgt_sdk
{
	return 0;
}

sub need_reinstall_opamgt_sdk
{
	return "no";
}

sub check_os_prereqs_opamgt_sdk
{
	return rpm_check_os_prereqs("opamgt_sdk", "user");
}

sub preinstall_opamgt_sdk
{
	return 0;
}

sub install_opamgt_sdk
{
	my $install_list = $_[0];       # total that will be installed when done
	my $installing_list = $_[1];    # what items are being installed/reinstalled

	my $version=media_version_opamgt_sdk();
	chomp $version;
	printf("Installing $ComponentInfo{'opamgt_sdk'}{'Name'} $version $DBG_FREE...\n");
	LogPrint "Installing $ComponentInfo{'opamgt_sdk'}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER\n";

	install_comp_rpms('opamgt_sdk', "", $install_list);

	$ComponentWasInstalled{'opamgt_sdk'}=1;
}

sub postinstall_opamgt_sdk
{

}

sub uninstall_opamgt_sdk
{
	my $install_list = $_[0];	# total that will be left installed when done
	my $uninstalling_list = $_[1];	# what items are being uninstalled

	uninstall_comp_rpms('opamgt_sdk', '', $install_list, $uninstalling_list, 'verbose');
	$ComponentWasInstalled{'opamgt_sdk'}=0;
}
#!/usr/bin/perl
## BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
# Copyright (c) 2020, Cornelis Networks, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
## END_ICS_COPYRIGHT8   ****************************************
#
## [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
#use strict;
##use Term::ANSIColor;
##use Term::ANSIColor qw(:constants);
##use File::Basename;
##use Math::BigInt;
#
## ==========================================================================
#
#Installation Prequisites array for opafm
my @opafm_prereq = (
			"bash",
			"expat",
			"glibc",
			"libibumad",
			"libibverbs",
			"openssl-libs",
			"rdma-core",
			"systemd",
			"zlib",
);
$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq;
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ==========================================================================
# OPA FM for OFA installation

# autostart functions are per subcomponent
# determine if the given capability is configured for Autostart at boot
sub IsAutostart2_opafm()
{
	return IsAutostart("opafm");
}
sub autostart_desc_opafm()
{
	return "$ComponentInfo{'opafm'}{'Name'} (opafm)";
}
# enable autostart for the given capability
sub enable_autostart2_opafm()
{
	enable_autostart("opafm");
}
# disable autostart for the given capability
sub disable_autostart2_opafm()
{
	disable_autostart("opafm");
}

sub get_rpms_dir_opafm
{
	my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'};
	return "$srcdir/RPMS/*";
}

sub available_opafm
{
	my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'};
	return (rpm_resolve("$srcdir/RPMS/*/opa-fm", "any") ne "");
}

sub installed_opafm
{
	return rpm_is_installed("opa-fm", "any");
}

# only called if installed_opafm is true
sub installed_version_opafm
{
	my $version = rpm_query_version_release_pkg("opa-fm");
	return dot_version("$version");
}

# only called if available_opafm is true
sub media_version_opafm
{
	my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'};
	my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opa-fm", "any");
	my $version= rpm_query_version_release("$rpmfile");
	# assume media properly built with matching versions
	return dot_version("$version");
}

sub build_opafm
{
	my $osver = $_[0];
	my $debug = $_[1];	# enable extra debug of build itself
	my $build_temp = $_[2];	# temp area for use by build
	my $force = $_[3];	# force a rebuild
	my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'};

	return 0;	# success
}

sub need_reinstall_opafm($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return "no";
}

sub preinstall_opafm
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled
	my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'};

	return 0;	# success
}

sub install_opafm
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled

	my $version=media_version_opafm();
	chomp $version;

	printf("Installing $ComponentInfo{'opafm'}{'Name'} $version $DBG_FREE...\n");
	LogPrint "Installing $ComponentInfo{'opafm'}{'Name'} $version $DBG_FREE for $CUR_OS_VER\n";

	# because RPM will change autostart settings of opafm we need to save
	# and restore the settings
	my $fm_start = IsAutostart2_opafm();

	# Install the rpm
	install_comp_rpms('opafm', " -U ", $install_list);

	check_rpm_config_file("$CONFIG_DIR/opa-fm/opafm.xml", "/etc/sysconfig");
	check_rpm_config_file("$CONFIG_DIR/opa-fm/opafm_pp.xml");
	check_dir("/usr/lib/opa");

	if ($fm_start) {
		enable_autostart("opafm");
	} else {
		disable_autostart("opafm");
	}

	$ComponentWasInstalled{'opafm'}=1;
}

sub postinstall_opafm
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled
}

sub uninstall_opafm
{
	my $install_list = $_[0];	# total that will be left installed when done
	my $uninstalling_list = $_[1];	# what items are being uninstalled

	NormalPrint("Uninstalling $ComponentInfo{'opafm'}{'Name'}...\n");

	uninstall_comp_rpms('opafm', '', $install_list, $uninstalling_list, 'verbose');
	# just in case, newer rpms should clean these up
	system("rm -rf /usr/lib/opa/.comp_opafm.pl");
	system("rmdir -p /opt/iba/fm_tools 2>/dev/null");  # remove only if empty
	system("rm -rf /usr/lib/opa-fm");
	$ComponentWasInstalled{'opafm'}=0;
}

sub check_os_prereqs_opafm
{
	return rpm_check_os_prereqs("opafm", "user");
}

#!/usr/bin/perl
## BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
# Copyright (c) 2020, Cornelis Networks, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
## END_ICS_COPYRIGHT8   ****************************************
#
## [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
#use strict;
##use Term::ANSIColor;
##use Term::ANSIColor qw(:constants);
##use File::Basename;
##use Math::BigInt;
#
## ==========================================================================
#
#Installation Prequisites array for delta components
my @opa_stack_prereq = (
    "bash",
    "kernel",
    "kmod",
    "rdma-core",
    "systemd",
    "glibc",
    "pciutils",
    "opensm-libs",
    "libibumad",
    "rdma-core-devel",
);
$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq;

my @mpi_selector_prereq = (
    "bash",
    "coreutils",
    "perl",
    "perl-Getopt-Long",
    "tcsh",
);
$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq;

my @intel_hfi_prereq = (
    "bash",
    "glibc",
    "libgcc",
    "python2",
    "systemd",
    "numactl-libs",
    "irqbalance",
    "libatomic",
);
$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq;

my @mvapich2_prereq = (
    "bash",
    "libibverbs",
    "librdmacm",
    "glibc",
    "zlib",
    "sysfsutils",
);
$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq;

my @openmpi_prereq = (
    "bash",
    "glibc",
    "libgcc",
    "libgfortran",
    "gcc-gfortran",
    "libgomp",
    "libibverbs",
    "libquadmath",
    "librdmacm",
    "libstdc++",
    "libstdc++-devel",
    "opensm-libs",
    "pkgconf",
    "zlib",
);
$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq;

my @mvapich2_gcc_hfi_prereq = (
    "bash",
    "zlib",
    "glibc",
);
$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq;

my @mvapich2_intel_hfi_prereq = (
    "bash",
);
$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq;

my @openmpi_gcc_hfi_prereq = (
    "bash",
    "glibc",
    "libgcc",
    "libgfortran",
    "gcc-gfortran",
    "libgomp",
    "libibverbs",
    "libquadmath",
    "librdmacm",
    "libstdc++",
    "libstdc++-devel",
    "opensm-libs",
    "pkgconf",
    "zlib",
);
$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq;

my @openmpi_intel_hfi_prereq = (
    "bash",
);
$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq;
#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8
#
# Copyright (c) 2015-2020, Intel Corporation
# Copyright (c) 2020-2021, Cornelis Networks, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8

# This file incorporates work covered by the following copyright and permission notice

#
# Copyright (c) 2006 Mellanox Technologies. All rights reserved.
#
# This Software is licensed under one of the following licenses:
#
# 1) under the terms of the "Common Public License 1.0" a copy of which is
#    available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/cpl.php.
#
# 2) under the terms of the "The BSD License" a copy of which is
#    available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/bsd-license.php.
#
# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
#    copy of which is available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/gpl-license.php.
#
# Licensee has the right to choose one of the above licenses.
#
# Redistributions of source code must retain the above copyright
# notice and one of the license notices.
#
# Redistributions in binary form must reproduce both the above copyright
# notice, one of the license notices in the documentation
# and/or other materials provided with the distribution.

use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ==========================================================================
# OFA_Delta installation, includes Intel value-adding packages only

# all kernel srpms
# these are in the order we must build/process them to meet basic dependencies
my @delta_kernel_srpms_rhel72 = ( 'kmod-ifs-kernel-updates' );
# the kernel srpm for HFI2
my @delta_kernel_srpms_rhel74_hfi2 = ( 'hfi2' );
my @delta_kernel_srpms_sles12_sp2 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles12_sp3 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles12_sp4 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles12_sp5 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles15 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles15_sp1 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles15_sp2 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_sles15_sp3 = ( 'ifs-kernel-updates-kmp-default' );
my @delta_kernel_srpms_rhel73 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel74 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel75 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel76 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel77 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel78 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel8 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel81 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel82 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel83 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel84 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms_rhel85 = ( 'kmod-ifs-kernel-updates' );
my @delta_kernel_srpms = ( );

# This provides information for all kernel srpms
# Only srpms listed in @delta_kernel_srpms are considered for install
# As such, this may list some srpms which are N/A to the selected distro
#
# Fields:
#	Available => indicate which platforms each srpm can be built for
#	Builds => list of kernel and user rpms built from each srpm
#				caller must know if user/kernel rpm is expected
#	PartOf => Components which the rpms built from this srpm are part of
my %delta_srpm_info = (
		# only used in sles12sp2
	"ifs-kernel-updates-kmp-default" =>        { Available => "",
					Builds => "ifs-kernel-updates-kmp-default ifs-kernel-updates-devel",
					PartOf => " opa_stack opa_stack_dev",
					},
		# only used in rhel72 and rhel73
	"kmod-ifs-kernel-updates" =>    { Available => "",
					Builds => "kmod-ifs-kernel-updates ifs-kernel-updates-devel",
					PartOf => " opa_stack opa_stack_dev",
					},
		# only use for HFI2. right now only in rhel74
	"hfi2" =>    { Available => "",
					Builds => "hfi2",
					PartOf => " opa_stack",
					},
);

my %delta_autostart_save = ();
# ==========================================================================
# Delta opa_stack build in prep for installation

# based on %delta_srpm_info{}{'Available'} determine if the given SRPM is
# buildable and hence available on this CPU for $osver combination
# "user" and kernel rev values for mode are treated same
sub available_srpm($$$)
{
	my $srpm = shift();
	# $mode can be any other value,
	# only used to select Available
	my $mode = shift();	# "user" or kernel rev
	my $osver = shift();
	my $avail ="Available";

	DebugPrint("checking $srpm $mode $osver against '$delta_srpm_info{$srpm}{$avail}'\n");
	return arch_kernel_is_allowed($osver, $delta_srpm_info{$srpm}{$avail});
}

# initialize delta srpm list based on specified osver
# for present system
sub init_delta_info($)
{
	my $osver = shift();

	# filter components by distro
	if ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES122') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp2 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES123') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp3 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES124') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp4 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES125') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp5 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES15') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles15 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES151') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles15_sp1 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES152') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles15_sp2 );
	} elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE'
		&& "$CUR_VENDOR_VER" eq 'ES153') {
		@delta_kernel_srpms = ( @delta_kernel_srpms_sles15_sp3 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES74" ) {
		if ($HFI2_INSTALL) {
			@delta_kernel_srpms = (@delta_kernel_srpms_rhel74_hfi2);
		} else {
			@delta_kernel_srpms = (@delta_kernel_srpms_rhel74);
		}
	} elsif ( "$CUR_VENDOR_VER" eq "ES85" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel85 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES84" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel84 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES83" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel83 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES82" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel82 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES81" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel81 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES8" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel8 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES78" || "$CUR_VENDOR_VER" eq "ES79" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel78 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES77" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel77 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES76" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel76 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES75" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel75 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES73" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel73 );
	} elsif ( "$CUR_VENDOR_VER" eq "ES72" ) {
		@delta_kernel_srpms = ( @delta_kernel_srpms_rhel72 );
	} else {
		# unknown distro, leave empty
		@delta_kernel_srpms = ( );
	}

	if (DebugPrintEnabled() ) {
		# dump all SRPM info
		DebugPrint "\nSRPMs:\n";
		foreach my $srpm ( @delta_kernel_srpms ) {
			DebugPrint("$srpm => Builds: '$delta_srpm_info{$srpm}{'Builds'}'\n");
			DebugPrint("           Available: '$delta_srpm_info{$srpm}{'Available'}'\n");
			DebugPrint("           Available: ".available_srpm($srpm, "user", $osver)." PartOf: '$delta_srpm_info{$srpm}{'PartOf'}'\n");
		}
		DebugPrint "\n";
	}
}

sub get_rpms_dir_delta($);

# verify the rpmfiles exist for all the RPMs listed
sub delta_rpm_exists_list($@)
{
	my $mode = shift();	#  "user" or kernel rev or "firmware"
	my(@package_list) = @_;	# package names

	foreach my $package ( @package_list )
	{
		next if ( "$package" eq '' );
		my $rpmdir = get_rpms_dir_delta("$package");
		if (! rpm_exists("$rpmdir/$package", $mode) ) {
			return 0;
		}
	}
	return 1;
}

# resolve filename within $srcdir/$SRPMS_SUBDIR
# and return filename relative to $srcdir
sub delta_srpm_file($$)
{
	my $srcdir = shift();
	my $globname = shift(); # in $srcdir
	my $result;

	if ( $GPU_Install == 1 ) {
		if ( -d $srcdir."/SRPMS/CUDA" ) {
			$result = file_glob("$srcdir/$SRPMS_SUBDIR/CUDA/$globname");
		} else {
			NormalPrint("CUDA specific SRPMs do not exist\n");
			exit 1;
		}
	} else {
		$result = file_glob("$srcdir/$SRPMS_SUBDIR/$globname");
	}

	$result =~ s|^$srcdir/||;
	return $result;
}

# indicate where DELTA built RPMs can be found
sub delta_rpms_dir()
{
	my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'};

	if (-d "$srcdir/$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_VER" ) {
		return "$srcdir/$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_VER";
	} else {
		return "$srcdir/$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_MAJOR_VER";
	}
}

# package is supplied since for a few packages (such as GPU Direct specific
# packages) we may pick a different directory based on package name
sub get_rpms_dir_delta($)
{
	my $package = shift();

	my $rpmsdir = delta_rpms_dir();

	# Note no need to check kernel levels since GPU Direct now supported
	# for all distros.  If we add a distro without this, such as Ubuntu,
	# perhaps argument parser should turn off GPU_Install on that distro.
	if ( $GPU_Install == 1
		 && ( $package =~ /ifs-kernel-updates/ || $package =~ /libpsm/) ) {
			if ( -d $rpmsdir."/CUDA" ) {
				$rpmsdir=$rpmsdir."/CUDA";
			} else {
				NormalPrint("CUDA specific packages do not exist\n");
				exit 1;
			}
	}
	return $rpmsdir;
}

# verify if all rpms have been built from the given srpm
sub is_built_srpm($$)
{
	my $srpm = shift();	# srpm name prefix
	my $mode = shift();	# "user" or kernel rev

	my @package_list = split /[[:space:]]+/, $delta_srpm_info{$srpm}{'Builds'};
	return ( delta_rpm_exists_list($mode, @package_list) );
}

# see if srpm is part of any of the components being installed/reinstalled
sub need_srpm_for_install($$$$)
{
	my $srpm = shift();	# srpm name prefix
	my $mode = shift();	# "user" or kernel rev
	my $osver = shift();
	# add space at start and end so can search
	# list with spaces around searched comp
	my $installing_list = " ".shift()." "; # items being installed/reinstalled

	if (! available_srpm($srpm, $mode, $osver)) {
		DebugPrint("$srpm $mode $osver not available\n");
		return 0;
	}

	my @complist = split /[[:space:]]+/, $delta_srpm_info{$srpm}{'PartOf'};
	foreach my $comp (@complist) {
		next if ("$comp" eq '');
		DebugPrint("Check for $comp in ( $installing_list )\n");
		if ($installing_list =~ / $comp /) {
			return 1;
		}
	}
	return 0;
}

sub need_build_srpm($$$$$$)
{
	my $srpm = shift();	# srpm name prefix
	my $mode = shift();	# "user" or kernel rev
	my $osver = shift();	# kernel rev
	my $installing_list = shift(); # what items are being installed/reinstalled
	my $force = shift();	# force a rebuild
	my $prompt = shift();	# prompt (only used if ! $force)

	return ( need_srpm_for_install($srpm, $mode, $osver, $installing_list)
			&& ($force
				|| ! is_built_srpm($srpm, $mode)
				|| ($prompt && GetYesNo("Rebuild $srpm src RPM for $mode?", "n"))));
}

# move rpms from build tree (srcdir) to install tree (destdir)
sub delta_move_rpms($$)
{
	my $srcdir = shift();
	my $destdir = shift();

	system("mkdir -p $destdir");
	if (file_glob("$srcdir/$RPM_ARCH/*") ne "" ) {
		system("mv $srcdir/$RPM_ARCH/* $destdir");
	}
	if (file_glob("$srcdir/$RPM_KERNEL_ARCH/*") ne "" ) {
		system("mv $srcdir/$RPM_KERNEL_ARCH/* $destdir");
	}
	if (file_glob("$srcdir/noarch/*") ne "" ) {
		system("mv $srcdir/noarch/* $destdir");
	}
}

# build all OFA components specified in installing_list
# if already built, prompt user for option to build
sub build_delta($$$$$$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift(); # what items are being installed/reinstalled
	my $K_VER = shift();	# osver
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild

	my $prompt_srpm = 0;	# prompt per SRPM
	my $force_srpm = $force;	# force SRPM rebuild
	my $force_kernel_srpm = 0;
	my $rpmsdir = delta_rpms_dir();

	# we only support building kernel code, so if user wants to skip install
	# of kernel, we have nothing to do here
	# TBD, if its selected to install opa_stack_dev and user_space_only we still
	# don't rebuild the kernel srpm, even though it creates the -devel package
	# However, that package is not kernel specific, so we should be ok
	if($user_space_only) {
		return 0;	# success
	}

	if (! $force && ! $Default_Prompt && ! $force_kernel_srpm) {
		my $choice = GetChoice("Rebuild OFA kernel SRPM (a=all, p=prompt per SRPM, n=only as needed?)", "n", ("a", "p", "n"));
		if ("$choice" eq "a") {
			$force_srpm=1;
		} elsif ("$choice" eq "p") {
			$prompt_srpm=1;
		} elsif ("$choice" eq "n") {
			$prompt_srpm=0;
		}
	}

	# -------------------------------------------------------------------------
	# do all rebuild prompting first so user doesn't have to wait 5 minutes
	# between prompts
	my %build_kernel_srpms = ();
	my $need_build = 0;
	my $build_compat_rdma = 0;

	# there will be exactly 1 srpm in delta_kernel_srpms
	foreach my $kernel_srpm ( @delta_kernel_srpms ) {
		$build_kernel_srpms{"${kernel_srpm}_build_kernel"} = need_build_srpm($kernel_srpm, "$K_VER", "$K_VER",
							$installing_list,
							$force_srpm || $force_kernel_srpm,
							$prompt_srpm);
		$need_build |= $build_kernel_srpms{"${kernel_srpm}_build_kernel"};
	}

	if (! $need_build) {
		return 0;	# success
	}

	# -------------------------------------------------------------------------
	# check OS dependencies for all srpms which we will build
	my $dep_error = 0;

	NormalPrint "Checking OS Dependencies needed for builds...\n";

	foreach my $srpm ( @delta_kernel_srpms ) {
		next if ( ! $build_kernel_srpms{"${srpm}_build_kernel"} );

		VerbosePrint("check dependencies for $srpm\n");
		if (check_kbuild_dependencies($K_VER, $srpm )) {
			DebugPrint "$srpm kbuild dependency failure\n";
			$dep_error = 1;
		}
		if (check_rpmbuild_dependencies($srpm)) {
			DebugPrint "$srpm rpmbuild dependency failure\n";
			$dep_error = 1;
		}
	}

	if ($dep_error) {
		NormalPrint "ERROR - unable to perform builds due to need for additional OS rpms\n";
		return 1;	# failure
	}

	# -------------------------------------------------------------------------
	# perform the builds
	my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'};

	# use a different directory for BUILD_ROOT to limit conflict with OFED
	if ("$build_temp" eq "" ) {
		$build_temp = "/var/tmp/CornelisOPX-DELTA";
	}
	my $BUILD_ROOT="$build_temp/build";
	my $RPM_DIR="$build_temp/DELTARPMS";
	my $resfileop = "replace";	# replace for 1st build, append for rest

	system("rm -rf ${build_temp}");

	# use a different directory for BUILD_ROOT to limit conflict with OFED
	if (0 != system("mkdir -p $BUILD_ROOT $RPM_DIR/BUILD $RPM_DIR/RPMS $RPM_DIR/SOURCES $RPM_DIR/SPECS $RPM_DIR/SRPMS")) {
		NormalPrint "ERROR - mkdir -p $BUILD_ROOT $RPM_DIR/BUILD $RPM_DIR/RPMS $RPM_DIR/SOURCES $RPM_DIR/SPECS $RPM_DIR/SRPMS FAILED\n";
		return 1;	# failure
	}

	foreach my $srpm ( @delta_kernel_srpms ) {
		VerbosePrint("process $srpm\n");

		next if (! $build_kernel_srpms{"${srpm}_build_kernel"});

		my $SRC_RPM = delta_srpm_file($srcdir, "$srpm*.src.rpm");

		# Deal with SLES renaming
		if ("$srpm" eq "kmod-ifs-kernel-updates"
			|| "$srpm" eq "ifs-kernel-updates-kmp-default") {
			$SRC_RPM = delta_srpm_file($srcdir, "ifs-kernel-updates*.src.rpm");
		}

		my $cmd = "rpmbuild --rebuild --define '_topdir $RPM_DIR'";
		$cmd .=		" --define 'dist  %{nil}'";
		$cmd .=		" --target $RPM_KERNEL_ARCH";
		# IFS - also set build_root so we can cleanup and avoid conflicts
		$cmd .=		" --buildroot '${BUILD_ROOT}'";
		$cmd .=		" --define 'build_root ${BUILD_ROOT}'";

	   	$cmd .=		" --define 'kver $K_VER'";

		$cmd .=		" $SRC_RPM";

		if (0 != run_build("$srcdir $SRC_RPM $RPM_KERNEL_ARCH $K_VER", "$srcdir", $cmd, "$resfileop")) {
			return 1;	# failure
		}
		$resfileop = "append";
		if ( $GPU_Install == 1 ) {
			delta_move_rpms("$RPM_DIR/$RPMS_SUBDIR", "$rpmsdir/CUDA");
		} else {
			delta_move_rpms("$RPM_DIR/$RPMS_SUBDIR", "$rpmsdir");
		}
	}

	if (! $debug) {
		system("rm -rf ${build_temp}");
	} else {
		LogPrint "Build remnants left in $BUILD_ROOT and $RPM_DIR\n";
	}

	return 0;	# success
}

# forward declarations
sub installed_delta_opa_stack();

# TBD - might not need any more
# return 0 on success, != 0 otherwise
sub uninstall_old_delta_rpms($$$)
{
	my $mode = shift();	# "user" or kernel rev or "firmware"
						# "any"- checks if any variation of package is installed
	my $verbosity = shift();
	my $message = shift();

	my $ret = 0;	# assume success
	my @packages = ();
	my @prev_release_rpms = ( "hfi1-psm-compat-devel","hfi1-psm","hfi1-psm-devel","hfi1-psm-debuginfo","libhfi1verbs","libhfi1verbs-devel", "ifs-kernel-updates" );

	if ("$message" eq "" ) {
		$message = "previous OFA Delta";
	}
	NormalPrint "\nUninstalling $message RPMs\n";

	# uninstall all present version OFA rpms, just to be safe
	foreach my $i ( "mpiRest", reverse(@Components) ) {
  		next if (! $ComponentInfo{$i}{'IsOFA'});
		@packages = (@packages, @{ $ComponentInfo{$i}{'DebugRpms'}});
		@packages = (@packages, @{ $ComponentInfo{$i}{'UserRpms'}});
		@packages = (@packages, @{ $ComponentInfo{$i}{'FirmwareRpms'}});
		@packages = (@packages, @{ $ComponentInfo{$i}{'KernelRpms'}});
	}

	# workaround LAM and other MPIs usng mpi-selector
	# we uninstall mpi-selector separately and ignore failures for its uninstall
	my @filtered_packages = ();
	my @rest_packages = ();
	foreach my $i ( @packages ) {
		if (scalar(grep /^$i$/, (@filtered_packages, @rest_packages)) > 0) {
			# skip, already in list
		} elsif ( "$i" eq "mpi-selector" ) {
			@rest_packages = (@rest_packages, "$i");
		} else {
			@filtered_packages = (@filtered_packages, "$i");
		}
	}

	# get rpms we are going to remove
	my $installed_mpi_rpms = "";
	foreach my $rpm (@{ $ComponentInfo{'mpiRest'}{'UserRpms'}}) {
		if (rpm_is_installed($rpm, "user")) {
			$installed_mpi_rpms .= " $rpm";
		}
	}

	$ret ||= rpm_uninstall_all_list_with_options($mode, " --nodeps ", $verbosity, @filtered_packages);

	if ($ret == 0 && $installed_mpi_rpms ne "") {
		NormalPrint "The following MPIs were removed because they are built from a different version of OPA.\n";
		NormalPrint "Please rebuild these MPIs if you still need them.\n  $installed_mpi_rpms\n";
	}

# TBD can simply handle mpi_selector component specially at end as a component
	# ignore errors uninstalling mpi-selector
	if (scalar(@rest_packages) != 0) {
		if (rpm_uninstall_all_list_with_options($mode, " --nodeps ", $verbosity, @rest_packages) && ! $ret) {
			NormalPrint "The previous errors can be ignored\n";
		}
	}

	if (rpm_uninstall_all_list_with_options($mode, " --nodeps ", $verbosity, @prev_release_rpms) && ! $ret) {
		NormalPrint "The previous errors can be ignored\n";
	}

	if ( $ret ) {
		NormalPrint "Unable to uninstall $message RPMs\n";
	}
	return $ret;
}


# TBD - might not need anymore
# remove any old stacks or old versions of the stack
# this is necessary before doing builds to ensure we don't use old dependent
# rpms
sub uninstall_prev_versions()
{
	if (! installed_delta_opa_stack) {
		return 0;
	} elsif (! comp_is_uptodate('opa_stack')) { # all delta_comp same version
		if (0 != uninstall_old_delta_rpms("any", "silent", "previous OFA DELTA")) {
			return 1;
		}
	}
	return 0;
}

sub has_version_delta()
{
	# check both current and old location
	# NOTE: When we upgrade/downgrade, the previous installation may have
	# different BASE_DIR. Ideally we shall figure out previous installation
	# location and then check version_delta there. For now, we are doing it
	# in static way by checking all possible locations.
	return -e "$BASE_DIR/version_delta"
		|| -e "$OLD_BASE_DIR/version_delta";
}

sub media_version_delta()
{
	# all OFA components at same version as opa_stack
	my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'};
	return `cat "$srcdir/Version"`;
}

sub delta_save_autostart()
{
	foreach my $comp ( @Components ) {
  		next if (! $ComponentInfo{$comp}{'IsOFA'});
  		if ($ComponentInfo{$comp}{'HasStart'}
			&& $ComponentInfo{$comp}{'StartupScript'} ne "") {
			$delta_autostart_save{$comp} = comp_IsAutostart2($comp);
		} else {
			$delta_autostart_save{$comp} = 0;
		}
	}
}

sub delta_restore_autostart($)
{
	my $comp = shift();

	if ( $delta_autostart_save{$comp} ) {
		comp_enable_autostart2($comp, 1);
	} else {
  		if ($ComponentInfo{$comp}{'HasStart'}
			&& $ComponentInfo{$comp}{'StartupScript'} ne "") {
			comp_disable_autostart2($comp, 1);
		}
	}
}

# makes sure needed OFA components are already built, builts/rebuilds as needed
# called for every delta component's preinstall, noop for all but
# first OFA component in installing_list
sub preinstall_delta($$$)
{
	my $comp = shift();			# calling component
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	# ignore non-delta components at start of installing_list
	my @installing = split /[[:space:]]+/, $installing_list;
	while (scalar(@installing) != 0
			&& ("$installing[0]" eq ""
  				|| ! $ComponentInfo{$installing[0]}{'IsOFA'} )) {
		shift @installing;
	}
	# now, only do work if $comp is the 1st delta component in installing_list
	if ("$comp" eq "$installing[0]") {
		delta_save_autostart();
		init_delta_info($CUR_OS_VER);

# TBD - do we really need this any more?
		# Before we do any builds make sure old stacks removed so we don't
		# build against the wrong version of dependent rpms
		if (0 != uninstall_prev_versions()) {
			return 1;
		}
		print_separator;
		my $version=media_version_delta();
		chomp $version;
		printf("Preparing OFA $version $DBG_FREE for Install...\n");
		LogPrint "Preparing OFA $version $DBG_FREE for Install for $CUR_OS_VER\n";
		return build_delta("$install_list", "$installing_list", "$CUR_OS_VER",0,"",$OFED_force_rebuild);
	} else {
		return 0;
	}
}

# ==========================================================================
# OFA DELTA generic routines

# OFA has a single start script but controls which ULPs are loaded via
# entries in $OPA_CONFIG (rdma.conf)
# change all StartupParams for given delta component to $newvalue
sub delta_comp_change_opa_conf_param($$)
{
	my $comp=shift();
	my $newvalue=shift();

	VerbosePrint("edit /$OPA_CONFIG $comp StartUp set to '$newvalue'\n");
	foreach my $p ( @{ $ComponentInfo{$comp}{'StartupParams'} } ) {
		change_opa_conf_param($p, $newvalue);
	}
}

# generic functions to handle autostart needs for delta components with
# more complex rdma.conf based startup needs.  These assume opa_stack handles
# the actual startup script.  Hence these focus on the rdma.conf parameters
# determine if the given capability is configured for Autostart at boot
sub IsAutostart_delta_comp2($)
{
	my $comp = shift();	# component to check
	my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'};
	my $ret = $WhichStartup eq "" ? 1 : IsAutostart($WhichStartup);	# just to be safe, test this too

	# to be true, all parameters must be yes
	foreach my $p ( @{ $ComponentInfo{$comp}{'StartupParams'} } ) {
			$ret &= ( read_opa_conf_param($p, "") eq "yes");
	}
	return $ret;
}
sub autostart_desc_delta_comp($)
{
	my $comp = shift();	# component to describe
	my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'};
	if ( "$WhichStartup" eq "" ) {
		return "$ComponentInfo{$comp}{'Name'}"
	} else {
		return "$ComponentInfo{$comp}{'Name'} ($WhichStartup)";
	}
}
# enable autostart for the given capability
sub enable_autostart_delta_comp2($)
{
	my $comp = shift();	# component to enable
	#my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'};

	#opa_stack handles this: enable_autostart($WhichStartup);
	delta_comp_change_opa_conf_param($comp, "yes");
}
# disable autostart for the given capability
sub disable_autostart_delta_comp2($)
{
	my $comp = shift();	# component to disable
	#my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'};

	delta_comp_change_opa_conf_param($comp, "no");
}

# helper to determine if we need to reinstall due to parameter change
sub need_reinstall_delta_comp($$$)
{
	my $comp = shift();
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	if (! comp_is_uptodate('opa_stack')) { # all delta_comp same version
		# on upgrade force reinstall to recover from uninstall of old rpms
		return "all";
	} else {
		return "no";
	}
}

# OFA has all the drivers in a single RPM.  This function installs that RPM
# ==========================================================================
# OFA Delta opa_stack installation

# determine if the given capability is configured for Autostart at boot
sub IsAutostart2_opa_stack()
{
	# opa_stack is tricky, there are multiple parameters.  We just test
	# the things we control here, if user has edited rdma.conf they
	# could end up with startup still disabled by having disabled all
	# the individual HCA drivers
	return IsAutostart_delta_comp2("opa_stack");
}
sub autostart_desc_opa_stack()
{
	return autostart_desc_delta_comp('opa_stack');
}
# enable autostart for the given capability
sub enable_autostart2_opa_stack()
{
	enable_autostart("opa");
}
# disable autostart for the given capability
sub disable_autostart2_opa_stack()
{
	disable_autostart("opa");
}

sub get_rpms_dir_opa_stack($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_opa_stack()
{
	my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'};
# TBD better checks for available?
	return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" );
}

sub installed_delta_opa_stack()
{
	if ( "$CUR_VENDOR_VER" eq "ES72" ) {
		return ( has_version_delta()
				&& (rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)
				    || rpm_is_installed("ifs-kernel-updates", $CUR_OS_VER)));
	} elsif ( "$CUR_VENDOR_VER" eq "ES73" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES74" ) {
		if ($HFI2_INSTALL) {
			return ( has_version_delta()
			      && rpm_is_installed("hfi2", $CUR_OS_VER));
		} else {
			return ( has_version_delta()
			      && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
		}
	} elsif ( "$CUR_VENDOR_VER" eq "ES85" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES84" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES83" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES82" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES81" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES8" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES78" || "$CUR_VENDOR_VER" eq "ES79" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES77" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES76" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES75" ) {
		return ( has_version_delta()
				&& rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES122' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES123' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES124' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES125' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES15' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES151' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES152' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq 'ES153' ) {
		return ( has_version_delta()
				&& rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} else {
		return 0;
	}
}

sub installed_opa_stack()
{
	return (installed_delta_opa_stack);
}

# only called if installed_opa_stack is true
sub installed_version_opa_stack()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return 'NONE';
	}
}

# only called if available_opa_stack is true
sub media_version_opa_stack()
{
	return media_version_delta();
}

# return 0 on success, 1 on failure
sub run_uninstall($$$)
{
	my $stack = shift();
	my $cmd = shift();
	my $cmdargs = shift();

	if ( "$cmd" ne "" && -e "$cmd" ) {
		NormalPrint "\nUninstalling $stack: $cmd $cmdargs\n";
		if (0 != system("yes | $cmd $cmdargs")) {
			NormalPrint "Unable to uninstall $stack\n";
			return 1;
		}
	}
	return 0;
}

# return 0 on success, !=0 on failure
sub build_opa_stack($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild

	init_delta_info($osver);

	# We can't remove old ib stack because we need them for build
	# OFA_DELTA. More importantly, we don't know where are the rpms.

	# Before we do any builds make sure old stacks removed so we don't
	# build against the wrong version of dependent rpms
	#if (0 != uninstall_prev_versions()) {
	#	return 1;
	#}

	return build_delta("@Components", "@Components", $osver, $debug,$build_temp,$force);
}

sub need_reinstall_opa_stack($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return (need_reinstall_delta_comp('opa_stack', $install_list, $installing_list));
}

sub check_os_prereqs_opa_stack
{
	return rpm_check_os_prereqs("opa_stack", "any");
}

sub preinstall_opa_stack($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return preinstall_delta("opa_stack", $install_list, $installing_list);
}

my $arptbl_tunning = "ARPTABLE_TUNING";
my $arptbl_tunning_desc = 'Adjust kernel ARP table size for large fabrics';
AddAnswerHelp("$arptbl_tunning", "$arptbl_tunning_desc");

sub install_opa_stack($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'};

	print_comp_install_banner('opa_stack');

	# do the following before we set any system env vars
	if ( $Default_SameAutostart ) {
		# set env vars to -1 for SRP and SRPT, so we keep the autostart option
		setup_env("OPA_SRP_LOAD", -1);
		setup_env("OPA_SRPT_LOAD", -1);
	}

	#override the udev permissions.
	install_udev_permissions("$srcdir/config");

	# setup environment variable so that RPM can configure limits conf
	setup_env("OPA_LIMITS_CONF", 1);
	# so setting up envirnment to install driver for this component. actual install is done by rpm
	setup_env("OPA_INSTALL_CALLER", 1);

	# Check $BASE_DIR directory ...exist
	check_config_dirs();
	check_dir("/usr/lib/opa");

	prompt_opa_conf_param("$arptbl_tunning", "$arptbl_tunning_desc", "y", 'OPA_ARPTABLE_TUNING');

	install_comp_rpms('opa_stack', " -U --nodeps ", $install_list);
	# rdma.conf values not directly associated with driver startup are left
	# untouched delta rpm install will keep existing value

	# prevent distro's open IB from loading
	#add_blacklist("ib_mthca");
	#add_blacklist("ib_ipath");
	disable_distro_ofed();

	# Take care of the configuration files for srptools
	check_rpm_config_file("/etc/srp_daemon.conf");
	check_rpm_config_file("/etc/logrotate.d/srp_daemon");
	check_rpm_config_file("/etc/rsyslog.d/srp_daemon.conf");

	need_reboot();
	$ComponentWasInstalled{'opa_stack'}=1;
}

sub postinstall_opa_stack($$)
{
	my $old_conf = 0;	# do we have an existing conf file
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	if ( -e "/$OPA_CONFIG" ) {
		if (0 == system("cp /$OPA_CONFIG /$OPA_CONFIG-save")) {
			$old_conf=1;
		}
	}

	# adjust rdma.conf autostart settings
	foreach my $c ( @Components )
	{
  		next if (! $ComponentInfo{$c}{'IsOFA'});
		if ($install_list !~ / $c /) {
			# disable autostart of uninstalled components
			# opa_stack is at least installed
			delta_comp_change_opa_conf_param($c, "no");
		} else {
			# retain previous setting for components being installed
			# set to no if initial install
			# TBD - should move this to rpm .spec file
			# the rpm might do this for us, repeat just to be safe
			foreach my $p ( @{ $ComponentInfo{$c}{'StartupParams'} } ) {
				my $old_value = "";
				if ( $old_conf ) {
					$old_value = read_opa_conf_param($p, "/$OPA_CONFIG-save");
				}
				if ( "$old_value" eq "" ) {
					$old_value = "no";
				}
				change_opa_conf_param($p, $old_value);
			}
		}
	}

	delta_restore_autostart('opa_stack');
}

# Do we need to do any of the stuff???
sub uninstall_opa_stack($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_comp_uninstall_banner('opa_stack');
	remove_blacklist("ib_qib");

	# allow open IB to load
	#remove_blacklist("ib_mthca");
	#remove_blacklist("ib_ipath");

	# the following is the work around for STL-14186. hfi2 rpm doesn't call depmod on uninstall, so we need to do it
	# here. After we resolve the issue, we shall remove the following 3 lines
	if ($HFI2_INSTALL) {
		set_run_depmod();
	}

	# uninstall mpiRest
	uninstall_comp_rpms('mpiRest', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');

	# If we call uninstall intel_hfi before this function, OPA_INSTALL_CALLER will be 1.
	# So we reset it back to zero here to ensure we will skip check in opa-scripts
	setup_env("OPA_INSTALL_CALLER", 0);
	uninstall_comp_rpms('opa_stack', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');
	remove_limits_conf;

	remove_udev_permissions;

	system("rm -rf $BASE_DIR/version_delta");
	system("rm -rf $OLD_BASE_DIR/version_delta");
	system("rm -rf /usr/lib/opa/.comp_delta.pl");
	system "rmdir /usr/lib/opa 2>/dev/null";	# remove only if empty
	system "rmdir $BASE_DIR 2>/dev/null";	# remove only if empty
	system "rmdir $OPA_CONFIG_DIR 2>/dev/null";	# remove only if empty

	need_reboot();
	$ComponentWasInstalled{'opa_stack'}=0;
}
# ==========================================================================
# intel_hfi installation

# determine if the given capability is configured for Autostart at boot
sub IsAutostart2_intel_hfi()
{
    return (! is_blacklisted('hfi1'));
}
sub autostart_desc_intel_hfi()
{
    return autostart_desc_delta_comp('intel_hfi');
}
# enable autostart for the given capability
sub enable_autostart2_intel_hfi()
{
	if (! IsAutostart2_intel_hfi()) {
		remove_blacklist('hfi1');
		rebuild_ramdisk();
	}
}
# disable autostart for the given capability
sub disable_autostart2_intel_hfi()
{
	if (IsAutostart2_intel_hfi()) {
		add_blacklist('hfi1');
		rebuild_ramdisk();
	}
}

sub get_rpms_dir_intel_hfi($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_intel_hfi()
{
    my $srcdir=$ComponentInfo{'intel_hfi'}{'SrcDir'};
        return (-d "$srcdir/SRPMS" || -d "$srcdir/RPMS" );
}

sub installed_intel_hfi()
{
	if (!rpm_is_installed("hfi1-firmware", "firmware")) {
		return 0;
	}

	if ( "$CUR_VENDOR_VER" eq "ES72" || "$CUR_VENDOR_VER" eq "ES73" ) {
        return (rpm_is_installed("libhfi1", "user")
		     && has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES122" ) {
		return (rpm_is_installed("libhfi1verbs-rdmav2", "user")
		     && has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES74" ) {
		if ($HFI2_INSTALL) {
			return (has_version_delta()
			     && rpm_is_installed("hfi2", $CUR_OS_VER));
		} else {
			return (has_version_delta()
			     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
		}
	} elsif ( "$CUR_VENDOR_VER" eq "ES75" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES76" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES77" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES78" || "$CUR_VENDOR_VER" eq "ES79" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES8" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES81" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES82" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES83" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES84" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES85" ) {
		return (has_version_delta()
		     && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES123" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES124" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES125" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES15" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES151" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES152" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} elsif ( "$CUR_VENDOR_VER" eq "ES153" ) {
		return (has_version_delta()
		     && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER));
	} else {
		return 0;
	}
}

# only called if installed_intel_hfi is true
sub installed_version_intel_hfi()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return "";
	}
}

# only called if available_intel_hfi is true
sub media_version_intel_hfi()
{
    return media_version_delta();
}

sub build_intel_hfi($$$$)
{
    my $osver = shift();
    my $debug = shift();    # enable extra debug of build itself
    my $build_temp = shift();       # temp area for use by build
    my $force = shift();    # force a rebuild
    return 0;       # success
}

sub need_reinstall_intel_hfi($$)
{
    my $install_list = shift();     # total that will be installed when done
    my $installing_list = shift();  # what items are being installed/reinstalled

    return (need_reinstall_delta_comp('intel_hfi', $install_list, $installing_list));
}

sub preinstall_intel_hfi($$)
{
    my $install_list = shift();     # total that will be installed when done
    my $installing_list = shift();  # what items are being installed/reinstalled

    return preinstall_delta("intel_hfi", $install_list, $installing_list);
}

sub install_intel_hfi($$)
{
    my $install_list = shift();     # total that will be installed when done
    my $installing_list = shift();  # what items are being installed/reinstalled

    print_comp_install_banner('intel_hfi');
    setup_env("OPA_INSTALL_CALLER", 1);

    install_comp_rpms('intel_hfi', " -U --nodeps ", $install_list);

    need_reboot();
    $ComponentWasInstalled{'intel_hfi'}=1;
}

sub postinstall_intel_hfi($$)
{
    my $install_list = shift();     # total that will be installed when done
    my $installing_list = shift();  # what items are being installed/reinstalled
    delta_restore_autostart('intel_hfi');

	rebuild_ramdisk();
}

sub uninstall_intel_hfi($$)
{
    my $install_list = shift();     # total that will be left installed when done
    my $uninstalling_list = shift();        # what items are being uninstalled

    print_comp_uninstall_banner('intel_hfi');
    setup_env("OPA_INSTALL_CALLER", 1);
    uninstall_comp_rpms('intel_hfi', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');
    need_reboot();
    $ComponentWasInstalled{'intel_hfi'}=0;
    remove_blacklist('hfi1');
    rebuild_ramdisk();
}

sub check_os_prereqs_intel_hfi
{
	return rpm_check_os_prereqs("intel_hfi", "any");
}

# ==========================================================================
# OFA opa_stack development installation

sub get_rpms_dir_opa_stack_dev($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_opa_stack_dev()
{
	my $srcdir=$ComponentInfo{'opa_stack_dev'}{'SrcDir'};
	return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" );
}

sub installed_opa_stack_dev()
{
	return (rpm_is_installed("ifs-kernel-updates-devel", $CUR_OS_VER) &&
		has_version_delta());
}

# only called if installed_opa_stack_dev is true
sub installed_version_opa_stack_dev()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return "";
	}
}

# only called if available_opa_stack_dev is true
sub media_version_opa_stack_dev()
{
	return media_version_delta();
}

sub build_opa_stack_dev($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild
	return 0;	# success
}

sub need_reinstall_opa_stack_dev($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return (need_reinstall_delta_comp('opa_stack_dev', $install_list, $installing_list));
}

sub preinstall_opa_stack_dev($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return preinstall_delta("opa_stack_dev", $install_list, $installing_list);
}

sub install_opa_stack_dev($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	print_comp_install_banner('opa_stack_dev');
	install_comp_rpms('opa_stack_dev', " -U --nodeps ", $install_list);

	$ComponentWasInstalled{'opa_stack_dev'}=1;
}

sub postinstall_opa_stack_dev($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled
	#delta_restore_autostart('opa_stack_dev');
}

sub uninstall_opa_stack_dev($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_comp_uninstall_banner('opa_stack_dev');
	uninstall_comp_rpms('opa_stack_dev', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');
	$ComponentWasInstalled{'opa_stack_dev'}=0;
}

# ==========================================================================
# OFA delta_ipoib installation

# determine if the given capability is configured for Autostart at boot
sub IsAutostart2_delta_ipoib()
{
	return IsAutostart_delta_comp2('delta_ipoib') || IsAutostart("ipoib");
}
sub autostart_desc_delta_ipoib()
{
	return autostart_desc_delta_comp('delta_ipoib');
}
# enable autostart for the given capability
sub enable_autostart2_delta_ipoib()
{
	enable_autostart_delta_comp2('delta_ipoib');
}
# disable autostart for the given capability
sub disable_autostart2_delta_ipoib()
{
	disable_autostart_delta_comp2('delta_ipoib');
	if (Exist_ifcfg("ib")) {
		print "$ComponentInfo{'delta_ipoib'}{'Name'} will autostart if ifcfg files exists\n";
		print "To fully disable autostart, it's recommended to also remove related ifcfg files\n";
		Remove_ifcfg("ib_ipoib","$ComponentInfo{'delta_ipoib'}{'Name'}","ib");
	}
}

sub get_rpms_dir_delta_ipoib($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_delta_ipoib()
{
	my $srcdir=$ComponentInfo{'delta_ipoib'}{'SrcDir'};
	return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" );
}

sub installed_delta_ipoib()
{
	return 1;
}

# only called if installed_delta_ipoib is true
sub installed_version_delta_ipoib()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return 'Unknown';
	}
}

# only called if available_delta_ipoib is true
sub media_version_delta_ipoib()
{
	return media_version_delta();
}

sub build_delta_ipoib($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild
	return 0;	# success
}

sub need_reinstall_delta_ipoib($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return (need_reinstall_delta_comp('delta_ipoib', $install_list, $installing_list));
}

sub preinstall_delta_ipoib($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return preinstall_delta("delta_ipoib", $install_list, $installing_list);
}

sub install_delta_ipoib($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	print_comp_install_banner('delta_ipoib');
	install_comp_rpms('delta_ipoib', " -U --nodeps ", $install_list);

	# bonding is more involved, require user to edit to enable that
	Config_ifcfg(1,"$ComponentInfo{'delta_ipoib'}{'Name'}","ib", "$FirstIPoIBInterface",1);
	check_network_config;
	#Config_IPoIB_cfg;
	need_reboot();
	$ComponentWasInstalled{'delta_ipoib'}=1;
}

sub postinstall_delta_ipoib($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled
	delta_restore_autostart('delta_ipoib');
}

sub uninstall_delta_ipoib($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_comp_uninstall_banner('delta_ipoib');
	uninstall_comp_rpms('delta_ipoib', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');
	Remove_ifcfg("ib_ipoib","$ComponentInfo{'delta_ipoib'}{'Name'}","ib");
	need_reboot();
	$ComponentWasInstalled{'delta_ipoib'}=0;
}

# ==========================================================================
# OFA DELTA mpi-selector installation

sub get_rpms_dir_mpi_selector($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_mpi_selector()
{
	my $srcdir=$ComponentInfo{'mpi_selector'}{'SrcDir'};
	return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" );
}

sub installed_mpi_selector()
{
	return (rpm_is_installed("mpi-selector", "user")
			&& has_version_delta());
}

# only called if installed_mpi_selector is true
sub installed_version_mpi_selector()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return "";
	}
}

# only called if available_mpi_selector is true
sub media_version_mpi_selector()
{
	return media_version_delta();
}

sub build_mpi_selector($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild
	return 0;	# success
}

sub need_reinstall_mpi_selector($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return (need_reinstall_delta_comp('mpi_selector', $install_list, $installing_list));
}

sub check_os_prereqs_mpi_selector
{
	return rpm_check_os_prereqs("mpi_selector", "any");
}

sub preinstall_mpi_selector($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return preinstall_delta("mpi_selector", $install_list, $installing_list);
}

sub install_mpi_selector($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	print_comp_install_banner('mpi_selector');
	install_comp_rpms('mpi_selector', " -U --nodeps ", $install_list);

	$ComponentWasInstalled{'mpi_selector'}=1;
}

sub postinstall_mpi_selector($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled
	#delta_restore_autostart('mpi_selector');
}

sub uninstall_mpi_selector($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_comp_uninstall_banner('mpi_selector');
	uninstall_comp_rpms('mpi_selector', '', $install_list, $uninstalling_list, 'verbose');
	$ComponentWasInstalled{'mpi_selector'}=0;
}

# ==========================================================================
# OFA delta_debug installation

# this is an odd component.  It consists of the debuginfo files which
# are built and identified in DebugRpms in other components.  Installing this
# component installs the debuginfo files for the installed components.
# uninstalling this component gets rid of all debuginfo files.
# uninstalling other components will get rid of individual debuginfo files
# for those components

sub get_rpms_dir_delta_debug($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_delta_debug()
{
	my $srcdir=$ComponentInfo{'delta_debug'}{'SrcDir'};
	return (( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS")
			&& ( "$CUR_DISTRO_VENDOR" ne "SuSE" && rpm_will_build_debuginfo()));
}

sub installed_delta_debug()
{
	return (rpm_is_installed("libibumad-debuginfo", "user") || rpm_is_installed("libpsm2-debuginfo", "user")
			&& has_version_delta());
}

# only called if installed_delta_debug is true
sub installed_version_delta_debug()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return "";
	}
}

# only called if available_delta_debug is true
sub media_version_delta_debug()
{
	return media_version_delta();
}

sub build_delta_debug($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild
	return 0;	# success
}

sub need_reinstall_delta_debug($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	my $reins = need_reinstall_delta_comp('delta_debug', $install_list, $installing_list);
	if ("$reins" eq "no" ) {
		# if delta components with DebugRpms have been added we need to reinstall
		# this component.  Note uninstall for individual components will
		# get rid of associated debuginfo files
		foreach my $comp ( @Components ) {
			# TBD can remove IsOFA test, the only
			# components with DebugRpms are for OFA delta debug
  			next if (! $ComponentInfo{$comp}{'IsOFA'});
			if ( " $installing_list " =~ / $comp /
				 && 0 != scalar(@{ $ComponentInfo{$comp}{'DebugRpms'}})) {
				return "this";
			}
		}
		
	}
	return $reins;
}

sub preinstall_delta_debug($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return preinstall_delta("delta_debug", $install_list, $installing_list);
}

sub install_delta_debug($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	my @list;

	print_comp_install_banner('delta_debug');
	install_comp_rpms('delta_debug', " -U --nodeps ", $install_list);

	# install DebugRpms for each installed component
	foreach my $comp ( @Components ) {
		# TBD can remove IsOFA test, the only
		# components with DebugRpms are for OFA delta debug
  		next if (! $ComponentInfo{$comp}{'IsOFA'});
		if ( " $install_list " =~ / $comp / ) {
			install_comp_rpm_list("$comp", "user", " -U --nodeps ",
							@{ $ComponentInfo{$comp}{'DebugRpms'}});
		}
	}

	$ComponentWasInstalled{'delta_debug'}=1;
}

sub postinstall_delta_debug($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled
	#delta_restore_autostart('delta_debug');
}

sub uninstall_delta_debug($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_comp_uninstall_banner('delta_debug');

	uninstall_comp_rpms('delta_debug', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');
	# uninstall debug rpms for all components
	foreach my $comp ( reverse(@Components) ) {
  		next if (! $ComponentInfo{$comp}{'IsOFA'});
		rpm_uninstall_list2("any", " --nodeps ", 'verbose',
					 @{ $ComponentInfo{$comp}{'DebugRpms'}});
	}
	$ComponentWasInstalled{'delta_debug'}=0;
}

# ==========================================================================
# OFA DELTA ibacm installation

# determine if the given capability is configured for Autostart at boot
sub IsAutostart2_ibacm()
{
	return IsAutostart_delta_comp2('ibacm');
}
sub autostart_desc_ibacm()
{
	return autostart_desc_delta_comp('ibacm');
}
# enable autostart for the given capability
sub enable_autostart2_ibacm()
{
	enable_autostart($ComponentInfo{'ibacm'}{'StartupScript'});
}
# disable autostart for the given capability
sub disable_autostart2_ibacm()
{
	disable_autostart($ComponentInfo{'ibacm'}{'StartupScript'});
}

sub get_rpms_dir_ibacm($)
{
	my $package = shift();
	return get_rpms_dir_delta($package)
}

sub available_ibacm()
{
	my $srcdir=$ComponentInfo{'ibacm'}{'SrcDir'};
	return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" );
}

sub installed_ibacm()
{
	return (rpm_is_installed("ibacm", "user")
			&& has_version_delta());
}

# only used on RHEL72, for other distros ibacm is only a SubComponent
# only called if installed_ibacm is true
sub installed_version_ibacm()
{
	if ( -e "$BASE_DIR/version_delta" ) {
		return `cat $BASE_DIR/version_delta`;
	} else {
		return "";
	}
}

# only called if available_ibacm is true
sub media_version_ibacm()
{
	return media_version_delta();
}

sub build_ibacm($$$$)
{
	my $osver = shift();
	my $debug = shift();	# enable extra debug of build itself
	my $build_temp = shift();	# temp area for use by build
	my $force = shift();	# force a rebuild
	return 0;	# success
}

sub need_reinstall_ibacm($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return (need_reinstall_delta_comp('ibacm', $install_list, $installing_list));
}

sub preinstall_ibacm($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return preinstall_delta("ibacm", $install_list, $installing_list);
}

sub install_ibacm($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	print_comp_install_banner('ibacm');
	install_comp_rpms('ibacm', " -U --nodeps ", $install_list);

	$ComponentWasInstalled{'ibacm'}=1;
}

sub postinstall_ibacm($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled
	delta_restore_autostart('ibacm');
}

sub uninstall_ibacm($$)
{
	my $install_list = shift();	# total that will be left installed when done
	my $uninstalling_list = shift();	# what items are being uninstalled

	print_comp_uninstall_banner('ibacm');

	uninstall_comp_rpms('ibacm', ' --nodeps ', $install_list, $uninstalling_list, 'verbose');
	$ComponentWasInstalled{'ibacm'}=0;
}

sub check_os_prereqs_ibacm
{
	return rpm_check_os_prereqs("ibacm", "user");
}

# ------------------------------------------------------------------
# # subroutines for rdma-ndd component
# # -----------------------------------------------------------------
sub installed_rdma_ndd()
{
        return (rpm_is_installed("infiniband-diags", "user"));
}

sub enable_autostart2_rdma_ndd()
{
        system "systemctl enable rdma-ndd >/dev/null 2>&1";
}

sub disable_autostart2_rdma_ndd()
{
        system "systemctl disable rdma-ndd >/dev/null 2>&1";
}

sub IsAutostart2_rdma_ndd()
{
        my $status = `systemctl is-enabled rdma-ndd`;
        if ( $status eq "disabled\n" || $status eq "" ){
                return 0;
        }
        else{
                return 1;
        }
}

# ------------------------------------------------------------------
# # subroutines for delta_srp component
# # -----------------------------------------------------------------
sub installed_delta_srp()
{
	if ( -f "/etc/rdma/rdma.conf" ) {
                return 1;
        }
        else {
                return 0;
        }

}

sub enable_autostart2_delta_srp()
{
	change_opa_conf_param("SRP_LOAD", "yes");
}

sub disable_autostart2_delta_srp()
{
	change_opa_conf_param("SRP_LOAD", "no");
}

sub IsAutostart2_delta_srp()
{
	my $status = read_opa_conf_param("SRP_LOAD", "");
	if ( $status eq "yes" ){
                return 1;
        }
        else{
                return 0;
        }
}

# ------------------------------------------------------------------
# # subroutines for delta_srpt component
# # -----------------------------------------------------------------
sub installed_delta_srpt()
{
	if ( -f "/etc/rdma/rdma.conf" ) {
		return 1;
	}
	else {
		return 0;
	}
}

sub enable_autostart2_delta_srpt()
{
	change_opa_conf_param("SRPT_LOAD", "yes");
}

sub disable_autostart2_delta_srpt()
{
	change_opa_conf_param("SRPT_LOAD", "no");
}

sub IsAutostart2_delta_srpt()
{
	my $status = read_opa_conf_param("SRPT_LOAD", "");
        if ( $status eq "yes" ){
                return 1;
        }
        else{
                return 0;
        }
}

#!/usr/bin/perl
# BEGIN_ICS_COPYRIGHT8 ****************************************
#
# Copyright (c) 2015-2020, Intel Corporation
# Copyright (c) 2020-2021, Cornelis Networks
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# END_ICS_COPYRIGHT8   ****************************************

# [ICS VERSION STRING: @(#) ./opaconfig 10_11_1_2_2 [02/08/22 15:28]
use strict;
#use Term::ANSIColor;
#use Term::ANSIColor qw(:constants);
#use File::Basename;
#use Math::BigInt;

# ===========================================================================
# Main menus, option handling and version handling for FF for OFA install
#

my $Build_OsVer=$CUR_OS_VER;
my $Build_Debug=0;	# should we provide more info for debug
my $Build_Temp="";	# temp area to use for build
my $Default_Build = 0;	# -B option used to select build
my $Build_Force = 0;# rebuild option used to force full rebuild
my $To_Show_Comps = 0; # indicate whether we need to show components or not

$FirstIPoIBInterface=0; # first device is ib0

	# Names of supported install components
	# must be listed in dependency order such that prereqs appear 1st
	# delta_debug must be last

my @OmniPathAllComponents = (
	"oftools", "intel_hfi", "opa_stack_dev", "fastfabric",
	"delta_ipoib", "opafm", "opamgt_sdk",
	"mvapich2_gcc_hfi", "mvapich2_intel_hfi",
	"openmpi_gcc_hfi", "openmpi_intel_hfi",
	"openmpi_gcc_cuda_hfi",
	"mvapich2_gcc",	"openmpi_gcc", #"mpiRest",
	"mpisrc", "delta_debug"	);

my @Components_rhel72 = ( "opa_stack", "ibacm", "mpi_selector",
		@OmniPathAllComponents);
my @Components_sles12_sp2 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_rhel73 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_sles12_sp3 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_sles12_sp4 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_sles12_sp5 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_sles15 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_sles15_sp1 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_sles15_sp2 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_sles15_sp3 = ( "opa_stack",
		@OmniPathAllComponents );
my @Components_rhel74 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel75 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel76 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel77 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel78 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel8 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel81 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel82 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel83 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel84 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );
my @Components_rhel85 = ( "opa_stack", "mpi_selector",
		@OmniPathAllComponents );

@Components = ( );

# RHEL7.2, ibacm is a full component with rpms to install
my @SubComponents_older = ( "rdma_ndd", "delta_srp", "delta_srpt" );
# RHEL7.3 and newer AND SLES12.2 and newer
my @SubComponents_newer = ( "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" );
@SubComponents = ( );

	# an additional "special" component which is always installed when
	# we install/upgrade anything and which is only uninstalled when everything
	# else has been uninstalled.  Typically this will be the opaconfig
	# file and related files absolutely required by it (such as wrapper_version)
$WrapperComponent = "opaconfig";

# This provides more detailed information about each Component in @Components
# since hashes are not retained in the order specified, we still need
# @Components and @SubComponents to control install and menu order
# Only items listed in @Components and @SubComponents are considered for install
# As such, this may list some components which are N/A to the selected distro
# Fields are as follows:
#	Name => full name of component/subcomponent for prompts
# 	DefaultInstall => default installation (State_DoNotInstall or State_Install)
#					  used only when available and ! installed
#	SrcDir => directory name within install media for component
# 	PreReq => other components which are prereqs of a given
#				component/subcomponent
#				Need space before and after each component name to
#				facilitate compares so that compares do not mistake names
#				such as mpidev for mpi
#	CoReq =>  other components which are coreqs of a given component
#				Note that CoReqs can also be listed as prereqs to provide
#				install verification as each component is installed,
#				however prereqs should only refer to items earlier in the list
#				Need space before and after each component name to
#				facilitate compares so that compares do not mistake names
#				such as mpidev for mpi
#	Hidden => component should not be shown in menus/prompts
#			  used for hidden PreReq.  Hidden components can't HasStart
#			  nor HasFirmware
#	Disabled =>  components/subcomponents which are disabled from installation
#	IsOFA =>  is an in-distro OFA component we upgrade (excludes MPI)
#	KernelRpms => kernel rpms for given component, in dependency order
#				These are rpms which are kernel version specific and
#				will have kernel uname -r in rpm package name.
#				For a given distro a separate version of each of these rpms
#				may exist per kernel.  These are always architecture dependent
#				Note KernelRpms are always installed before FirmwareRpms and
#				UserRpms
#	FirmwareRpms => firmware rpms for given component, in dependency order
#				These are rpms which are not kernel specific.  For a given
#				distro a single version of each of these rpms will
#				exist per distro/arch combination.  In most cases they will
#				be architecture independent (noarch).
#				These are rpms which are installed in user space but
#				ultimately end up in hardware such as HFI firmware, TMM firmware
#				BIOS firmware, etc.
#	UserRpms => user rpms for given component, in dependency order
#				These are rpms which are not kernel specific.  For a given
#				distro a single version of each of these rpms will
#				exist per distro/arch combination.  Some of these may
#				be architecture independent (noarch).
#	DebugRpms => user rpms for component which should be installed as part
#				of delta_debug component.
#	HasStart =>  components/subcomponents which have autostart capability
#	DefaultStart =>  should autostart default to Enable (1) or Disable (0)
#				Not needed/ignored unless HasStart=1
# 	StartPreReq => other components/subcomponents which must be autostarted
#				before autostarting this component/subcomponent
#				Not needed/ignored unless HasStart=1
#				Need space before and after each component name to
#				facilitate compares so that compares do not mistake names
#				such as mpidev for mpi
#	StartComponents => components/subcomponents with start for this component
#				if a component has a start script
#				list the component as a subcomponent of itself
#	StartupScript => name of startup script which controls startup of this
#				component
#	StartupParams => list of parameter names in $OPA_CONFIG which control
#				startup of this component (set to yes/no values)
#	HasFirmware =>  components which need HCA firmware update after installed
#
# Note both Components and SubComponents are included in the list below.
# Components require all fields be supplied
# SubComponents only require the following fields:
#	Name, PreReq (should reference only components), HasStart, StartPreReq,
#	DefaultStart, and optionally StartupScript, StartupParams
#	Also SubComponents only require the IsAutostart2_X, autostart_desc_X,
#	enable_autostart2_X, disable_autostart2_X and installed_X functions.
#	Typically installed_X for a SubComponent will simply call installed_X for
#	the component which contains it.
%ComponentInfo = (
		# our special WrapperComponent, limited use
	"opaconfig" =>	{ Name => "opaconfig",
					  DefaultInstall => $State_Install,
					  SrcDir => ".",
					  PreReq => "", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]

					},
	"oftools" =>	{ Name => "OPA Tools",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-Tools*.*"),
					  PreReq => " opa_stack ", CoReq => " opa_stack ",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-basic-tools", "opa-address-resolution" ],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => " opa_stack ", # TBD
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"mpi_selector" =>	{ Name => "MPI selector",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 1, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "mpi-selector" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"fastfabric" =>	{ Name => "FastFabric",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-Tools*.*"),
					  PreReq => " opa_stack oftools ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-fastfabric", "opa-mpi-apps" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
# TBD - only a startup script, should act like a subcomponent only
	"delta_ipoib" =>	{ Name => "OFA IP over IB",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ ],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "delta_ipoib" ],
					  StartupScript => "",
					  StartupParams => [ "IPOIB_LOAD" ]
					},
	"mvapich2_gcc" =>	{ Name => "MVAPICH2 (verbs,gcc)",
					  DefaultInstall => $State_DoNotInstall,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack mpi_selector intel_hfi ", CoReq => "",
					  Hidden => 1, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "mvapich2_gcc", "mpitests_mvapich2_gcc" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"openmpi_gcc" =>	{ Name => "OpenMPI (verbs,gcc)",
					  DefaultInstall => $State_DoNotInstall,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack mpi_selector intel_hfi ", CoReq => "",
					  Hidden => 1, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "openmpi_gcc", "mpitests_openmpi_gcc" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"openmpi_gcc_cuda_hfi" =>{ Name => "OpenMPI (cuda,gcc)",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "",
					  Hidden => 1, Disabled => 1, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "openmpi_gcc_cuda_hfi", "mpitests_openmpi_gcc_cuda_hfi" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"mvapich2_gcc_hfi" =>	{ Name => "MVAPICH2 (hfi,gcc)",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "mvapich2_gcc_hfi", "mpitests_mvapich2_gcc_hfi" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"mvapich2_intel_hfi" =>	{ Name => "MVAPICH2 (hfi,Intel)",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "",
					  Hidden => 1, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "mvapich2_intel_hfi", "mpitests_mvapich2_intel_hfi" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"openmpi_gcc_hfi" =>	{ Name => "OpenMPI (hfi,gcc)",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "openmpi_gcc_hfi", "mpitests_openmpi_gcc_hfi" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"openmpi_intel_hfi" =>	{ Name => "OpenMPI (hfi,Intel)",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "",
					  Hidden => 1, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "openmpi_intel_hfi", "mpitests_openmpi_intel_hfi" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
# rest of MPI stuff which customer can build via do_build
# this is included here so we can uninstall
# special case use in comp_delta.pl, omitted from Components list
# TBD - how to best refactor this so we remove these (do we still need to remove them?)
	"mpiRest" =>	{ Name => "MpiRest (pgi,Intel)",
					  DefaultInstall => $State_DoNotInstall,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => "", CoReq => "",
					  Hidden => 1, Disabled => 1, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "mvapich2_pgi",
									"mvapich2_intel", "mvapich2_pathscale",
									"mvapich2_pgi_qlc", "mvapich2_gcc_qlc",
									"mvapich2_intel_qlc", "mvapich2_pathscale_qlc",
									"mvapich2_pgi_hfi", "mvapich2_pathscale_hfi",
									"mvapich2_pgi_cuda_hfi", "mvapich2_pathscale_cuda_hfi",
									"openmpi_pgi",
									"openmpi_intel", "openmpi_pathscale",
									"openmpi_pgi_qlc", "openmpi_gcc_qlc",
									"openmpi_intel_qlc", "openmpi_pathscale_qlc",
									"openmpi_pgi_hfi", "openmpi_pathscale_hfi",
									"openmpi_pgi_cuda_hfi", "openmpi_pathscale_cuda_hfi",
									"mpitests_mvapich2_pgi",
									"mpitests_mvapich2_intel",
									"mpitests_mvapich2_pathscale",
									"mpitests_mvapich2_pgi_qlc", "mpitests_mvapich2_gcc_qlc",
									"mpitests_mvapich2_intel_qlc", "mpitests_mvapich2_pathscale_qlc",
									"mpitests_mvapich2_pgi_hfi", "mpitests_mvapich2_pathscale_hfi",
									"mpitests_mvapich2_pgi_cuda_hfi", "mpitests_mvapich2_pathscale_cuda_hfi",
									"mpitests_openmpi_pgi",
									"mpitests_openmpi_intel",
									"mpitests_openmpi_pathscale",
									"mpitests_openmpi_pgi_qlc", "mpitests_openmpi_gcc_qlc",
									"mpitests_openmpi_intel_qlc", "mpitests_openmpi_pathscale_qlc",
									"mpitests_openmpi_pgi_hfi", "mpitests_openmpi_pathscale_hfi",
									"mpitests_openmpi_pgi_cuda_hfi", "mpitests_openmpi_pathscale_cuda_hfi",
								],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"mpisrc" =>{ Name => "MPI Source",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob ("./OFA_MPIS.*"),
					  PreReq => " opa_stack opa_stack_dev mpi_selector ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"opafm" =>	{ Name => "OPA FM",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-FM.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-fm", "opa-fm-debuginfo" ],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  #StartComponents => [ "qlgc_fm", "qlgc_fm_snmp"],
					  StartComponents => [ "opafm" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	"opamgt_sdk" => { Name => "OPA Management SDK",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-Tools*.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 0,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-libopamgt", "opa-libopamgt-devel" ],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
				  },
	"delta_debug" =>	{ Name => "OFA Debug Info",
					  DefaultInstall => $State_DoNotInstall,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ ],
					  DebugRpms => [ ],	# listed per comp
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
		# rdma_ndd is a subcomponent
		# it has a startup, but is considered part of opa_stack
	"rdma_ndd" =>		{ Name => "RDMA NDD",
					  PreReq => " opa_stack ",
					  HasStart => 1, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "rdma_ndd" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
		# delta_srp is a subcomponent
		# it has a startup, but is considered part of opa_stack
	"delta_srp" =>		{ Name => "OFA SRP",
					  PreReq => " opa_stack ",
					  HasStart => 1, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "delta_srp" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
		# delta_srpt is a subcomponent
		# it has a startup, but is considered part of opa_stack
	"delta_srpt" =>		{ Name => "OFA SRPT",
					  PreReq => " opa_stack ",
					  HasStart => 1, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "delta_srpt" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
	);

# We can improve ComponentInfo to include the following. But since they are used
# for mpisrc only, extending ComponentInfo doesn't benefit other components.
# We directly define them here where
#     Dest => installation location
#     SrcRpms => src rpms to install
#     BuildScripts => build script to install
#     MiscFiles => misc files, such as version file. This field includes 'Dest'
#                  and 'Src' to define the installed file name and source file
#                  name. For SrcRpms and BuildScript fields, the installed file
#                  name will be the same name as source file.
#     DirtyFiles => dirty files will be cleared during install/uninstall, such
#                   as the build generated files.
%ExtraMpisrcInfo = (
	Dest => "/usr/src/opa/MPI",
	SrcRpms => ["mvapich2", "openmpi", "mpitests"],
	BuildScripts => ["do_build", "do_mvapich2_build", "do_openmpi_build"],
	MiscFiles => [{
		Dest => ".version",
		Src => "version"}],
	DirtyFiles => [ "{mvapich2,openmpi,mpitests}_*.rpm",
	                "make.*.{res,err,warn}", ".mpiinfo"]
);

# one of these opa_stack comp_info gets appended to ComponentInfo
# for RHEL72
my %opa_stack_rhel72_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "kmod-ifs-kernel-updates" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad",
									"srptools",
									"libibmad",
									"infiniband-diags",
								],
					  DebugRpms => [ #"libibumad-debuginfo",
									"srptools-debuginfo",
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);
# for RHEL73
my %opa_stack_rhel73_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "kmod-ifs-kernel-updates" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad",
									#"srptools",
									#"libibmad",
									"infiniband-diags",
								],
					  DebugRpms => [ #"libibumad-debuginfo",
									#"srptools-debuginfo",
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);
# for RHEL74 and above
my %opa_stack_rhel_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "kmod-ifs-kernel-updates" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad",
									#"srptools",
									#"libibmad",
									#"infiniband-diags",
								],
					  DebugRpms => [ #"libibumad-debuginfo",
									#"srptools-debuginfo",
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);
# for RHEL74 HFI2
my %opa_stack_rhel74_hfi2_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "hfi2" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad",
									#"srptools",
									#"libibmad",
									#"infiniband-diags",
								],
					  DebugRpms => [ #"libibumad-debuginfo",
									#"srptools-debuginfo",
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);
# for SLES12sp2
my %opa_stack_sles12_sp2_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-kmp-default" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad3",
									#"srptools",
									#"libibmad5",
									"infiniband-diags",
								],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);
# for SLES12sp3
my %opa_stack_sles12_sp3_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-kmp-default" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad3",
									#"srptools",
									#"libibmad5",
									#"infiniband-diags",
								],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);

# for SLES12sp4
my %opa_stack_sles12_sp4_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-kmp-default" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
								],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);

# for SLES12sp5
my %opa_stack_sles12_sp5_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-kmp-default" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
								],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);

# for SLES15.x
my %opa_stack_sles15_comp_info = (
	"opa_stack" =>	{ Name => "OFA OPA Stack",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => "", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-kmp-default" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "opa-scripts",
									#"libibumad3",
									#"srptools",
									#"libibmad5",
									#"infiniband-diags",
								],
					  DebugRpms => [ ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => "",
					  StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ],
					  StartupScript => "opa",
					  StartupParams => [ "ARPTABLE_TUNING" ]
					},
);


# one of these ibacm comp_info gets appended to ComponentInfo
# for RHEL72
my %ibacm_older_comp_info = (
	"ibacm" =>		{ Name => "OFA IBACM",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "ibacm",],
					  DebugRpms => [ "ibacm-debuginfo" ],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "ibacm" ],
					  StartupScript => "ibacm",
					  StartupParams => [ ]
					},
);

# For RHEL73, SLES12sp2 and other newer distros
		# ibacm is a subcomponent
		# it has a startup, but is considered part of opa_stack
my %ibacm_comp_info = (
		# TBD - should be a StartComponent only for these distros
	"ibacm" =>		{ Name => "OFA IBACM",
					  PreReq => " opa_stack ",
					  HasStart => 1, DefaultStart => 0,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "ibacm" ],
					  StartupScript => "ibacm",
					  StartupParams => [ ]
					},
);


# one of these intel_hfi comp_info gets appended to ComponentInfo
# for RHEL72 which lacks libhfi1
my %intel_hfi_older_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms =>	  [ "libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ "hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", "libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);
# for RHEL73, SLES12.2 and other newer distros which include libhfi1
my %intel_hfi_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);
#
# for RHEL8, which does not currently support opa_stack and does not require libfabric-psm
my %intel_hfi_rhel8_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_rhel81_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_rhel82_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_rhel83_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_rhel84_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_rhel85_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

# For SLES12sp3 that has different name for libpsm2
my %intel_hfi_sles123_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2-2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_sles124_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ 		"libpsm2-2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ 		"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", 
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

my %intel_hfi_sles125_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ 		"libpsm2-2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ 		"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", 
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

# For SLES15.x that has different name for libpsm2
my %intel_hfi_sles15_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2-2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

# for RHEL74 HFI2
my %intel_hfi__rhel74_hfi2_comp_info = (
	"intel_hfi" =>	{ Name => "Cornelis HFI Components",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => " oftools ",
						# TBD - HasFirmware - FW update
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ ],
					  FirmwareRpms => [
									"hfi1-firmware", "hfi1-firmware_debug"
								],
					  UserRpms => [ #"libhfi1", "libhfi1-static",
									"libpsm2",
									"libpsm2-devel", "libpsm2-compat",
									"libfabric", "libfabric-devel",
									"libfabric-fxr",
									"libfabric-psm",
									"libfabric-psm2", "libfabric-verbs",
									"hfi1-diagtools-sw", "hfidiags",
								],
					  DebugRpms =>  [ #"hfi1_debuginfo",
									"hfi1-diagtools-sw-debuginfo",
									"libpsm2-debuginfo", #"libhfi1-debuginfo"
								],
					  HasStart => 1, HasFirmware => 0, DefaultStart => 1,
					  StartPreReq => " opa_stack ",
					  StartComponents => [ "intel_hfi" ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);
# one of these opa_stack_dev comp_info gets appended to ComponentInfo
# for RHEL72
my %opa_stack_dev_rhel72_comp_info = (
	"opa_stack_dev" => { Name => "OFA OPA Development",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-devel" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ "ibacm-devel",
									#"libibumad-devel", "libibumad-static",
									#"libibmad-devel", "libibmad-static"
									],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);
# for RHEL73 and SLES12sp2 and newer distros
my %opa_stack_dev_comp_info = (
	"opa_stack_dev" => { Name => "OFA OPA Development",
					  DefaultInstall => $State_Install,
					  SrcDir => file_glob("./CornelisOPX-OFA_DELTA.*"),
					  PreReq => " opa_stack ", CoReq => "",
					  Hidden => 0, Disabled => 0, IsOFA => 1,
					  KernelRpms => [ "ifs-kernel-updates-devel" ],
					  FirmwareRpms => [ ],
					  UserRpms => [ #"ibacm-devel",
									#"libibumad-devel", "libibumad-static",
									#"libibmad-devel", "libibmad-static"
									],
					  DebugRpms => [ ],
					  HasStart => 0, HasFirmware => 0, DefaultStart => 0,
					  StartPreReq => "",
					  StartComponents => [ ],
					  StartupScript => "",
					  StartupParams => [ ]
					},
);

	# translate from startup script name to component/subcomponent name
%StartupComponent = (
				"opa_stack" => "opa_stack",
				"opafm" => "opafm",
			);
	# has component been loaded since last configured autostart
%ComponentWasInstalled = (
				"opa_stack" => 0,
				"ibacm" => 0,
				"oftools" => 0,
				"mpi_selector" => 0,
				"opa_stack_dev" => 0,
				"fastfabric" => 0,
				"delta_ipoib" => 0,
				"mvapich2_gcc" => 0,
				"openmpi_gcc" => 0,
				"mvapich2_gcc_hfi" => 0,
				"mvapich2_intel_hfi" => 0,
				"openmpi_gcc_hfi" => 0,
				"openmpi_gcc_cuda_hfi" => 0,
				"openmpi_intel_hfi" => 0,
				"mpiRest" => 0,
				"mpisrc" => 0,
				"opafm" => 0,
				"opamgt_sdk" => 0,
				"delta_debug" => 0,
				"rdma_ndd" => 0,
				"delta_srp" => 0,
				"delta_srpt" => 0,
			);

# check whether we support HFI2
sub support_HFI2()
{
	# right now we support HFI2 only in RHEL7.4 with kVer >= 4.6
	if ("$CUR_VENDOR_VER" eq "ES74" && $CUR_OS_VER_SHORT >= 4.6) {
		# We prefer to check it based on feature (i.e. hfi2 pkg) rather than version (i.e. content in version file)
		my $rpmdir = "$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_VER";
		my $srcdir = $opa_stack_rhel74_hfi2_comp_info{'opa_stack'}{'SrcDir'};
		my @rpmlist = @{$opa_stack_rhel74_hfi2_comp_info{'opa_stack'}{'KernelRpms'}};
		# this function get called before overrides, so we need to consider the case we run it from DELTA pkg that
		# srcdir is current location, i.e. "."
		return rpm_exists_list("$srcdir/$rpmdir", $CUR_OS_VER, @rpmlist) ||
		       rpm_exists_list("./$rpmdir", $CUR_OS_VER, @rpmlist);
	}
	return 0;
}

sub init_components
{
	$HFI2_INSTALL = support_HFI2();

	# The component list has slight variations per distro
	if ( "$CUR_VENDOR_VER" eq "ES72" ) {
		@Components = ( @Components_rhel72 );
		@SubComponents = ( @SubComponents_older );
		%ComponentInfo = ( %ComponentInfo, %ibacm_older_comp_info,
						%intel_hfi_older_comp_info,
						%opa_stack_dev_rhel72_comp_info,
						%opa_stack_rhel72_comp_info,
						);
		$ComponentInfo{'oftools'}{'PreReq'} = " opastack ibacm ";
	} elsif ( "$CUR_VENDOR_VER" eq "ES122" ) {
		@Components = ( @Components_sles12_sp2 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles12_sp2_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES73" ) {
		@Components = ( @Components_rhel73 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel73_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES123" ) {
		@Components = ( @Components_sles12_sp3 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles123_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles12_sp3_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES124" ) {
		@Components = ( @Components_sles12_sp4 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles124_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles12_sp4_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES125" ) {
		@Components = ( @Components_sles12_sp5 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles125_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles12_sp5_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES74" ) {
		@SubComponents = ( @SubComponents_newer );
		@Components = ( @Components_rhel74 );
		if ($HFI2_INSTALL) {
			%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
							%intel_hfi__rhel74_hfi2_comp_info,
							%opa_stack_dev_comp_info,
							%opa_stack_rhel74_hfi2_comp_info,
							);
		} else {
			%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
							%intel_hfi_comp_info,
							%opa_stack_dev_comp_info,
							%opa_stack_rhel_comp_info,
							);
		}
	} elsif ( "$CUR_VENDOR_VER" eq "ES75" ) {
		@Components = ( @Components_rhel75 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES76" ) {
		@Components = ( @Components_rhel76 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES77" ) {
		@Components = ( @Components_rhel77 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES78" || "$CUR_VENDOR_VER" eq "ES79" ) {
		@Components = ( @Components_rhel78 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES8" ) {
		@Components = ( @Components_rhel8 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_rhel8_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES81" ) {
		@Components = ( @Components_rhel81 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_rhel81_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES82" ) {
		@Components = ( @Components_rhel82 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_rhel82_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES83" ) {
		@Components = ( @Components_rhel83 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_rhel83_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES84" ) {
		@Components = ( @Components_rhel84 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_rhel84_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES85" ) {
		@Components = ( @Components_rhel85 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_rhel85_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_rhel_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES15" ) {
		@Components = ( @Components_sles15 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles15_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles15_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES151" ) {
		@Components = ( @Components_sles15_sp1 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles15_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles15_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES152" ) {
		@Components = ( @Components_sles15_sp2 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles15_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles15_comp_info,
						);
	} elsif ( "$CUR_VENDOR_VER" eq "ES153" ) {
		@Components = ( @Components_sles15_sp3 );
		@SubComponents = ( @SubComponents_newer );
		%ComponentInfo = ( %ComponentInfo, %ibacm_comp_info,
						%intel_hfi_sles15_comp_info,
						%opa_stack_dev_comp_info,
						%opa_stack_sles15_comp_info,
						);
	} else {
		# unknown or unsupported distro, leave lists empty
		# verify_distrib_files will catch unsupported distro
		@Components = ( );
		@SubComponents = ( );
	}
}

# ==========================================================================
# opaconfig installation
# This is a special WrapperComponent which only needs:
#	available, install and uninstall
# it cannot have startup scripts, dependencies, prereqs, etc

sub available_opaconfig
{
	my $srcdir=$ComponentInfo{'opaconfig'}{'SrcDir'};
	return (rpm_resolve("$srcdir/*/opaconfig", "any"));
}

sub installed_opaconfig
{
	return rpm_is_installed("opaconfig", "any");
}

sub installed_version_opaconfig
{
	my $version = rpm_query_version_release_pkg("opaconfig");
	return dot_version("$version");
}

sub media_version_opaconfig
{
	my $srcdir = $ComponentInfo{'opaconfig'}{'SrcDir'};
	my $rpm = rpm_resolve("$srcdir/RPMS/*/opaconfig", "any");
	my $version = rpm_query_version_release($rpm);
	return dot_version("$version");
}

sub build_opaconfig
{
	my $osver = $_[0];
	my $debug = $_[1];      # enable extra debug of build itself
	my $build_temp = $_[2]; # temp area for use by build
	my $force = $_[3];      # force a rebuild
	return 0;       # success
}

sub need_reinstall_opaconfig($$)
{
	my $install_list = shift();	# total that will be installed when done
	my $installing_list = shift();	# what items are being installed/reinstalled

	return "no";
}

sub check_os_prereqs_opaconfig
{
	return rpm_check_os_prereqs("opaconfig", "user");
}

sub preinstall_opaconfig
{
        my $install_list = $_[0];       # total that will be installed when done
        my $installing_list = $_[1];    # what items are being installed/reinstalled

        return 0;       # success
}

sub install_opaconfig
{
	my $install_list = $_[0];	# total that will be installed when done
	my $installing_list = $_[1];	# what items are being installed/reinstalled

	my $srcdir=$ComponentInfo{'opaconfig'}{'SrcDir'};
	NormalPrint("Installing $ComponentInfo{'opaconfig'}{'Name'}...\n");

	# all meta pkgs depend on opaconfig. We may directly upgrade opaconfig, so we remove them first.
	rpm_uninstall_matches("opameta_", "opameta_", "", "");

	# New Install Code
	my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opaconfig", "any");
	rpm_run_install($rpmfile, "any", " -U ");
	# New Install Code

	# remove the old style version file
	system("rm -rf /$BASE_DIR/version");
	# version_wrapper is only for support (fetched in opacapture)
	system("echo '$VERSION' > $BASE_DIR/version_wrapper 2>/dev/null");
	# make sure we cleanup possibly old opaconfig_* files
	system("rm -rf /sbin/opa_config_ff");
	system("rm -rf /sbin/opa_config_fm");
	system("rm -rf /sbin/opa_config_srp");
	system("rm -rf /sbin/opa_config_vnic");
	system("rm -rf /sbin/opa_config_delta");

	$ComponentWasInstalled{'opaconfig'}=1;
}

sub postinstall_opaconfig
{
        my $install_list = $_[0];       # total that will be installed when done
        my $installing_list = $_[1];    # what items are being installed/reinstalled
}

sub uninstall_opaconfig
{
	my $install_list = $_[0];	# total that will be left installed when done
	my $uninstalling_list = $_[1];	# what items are being uninstalled

	NormalPrint("Uninstalling $ComponentInfo{'opaconfig'}{'Name'}...\n");

	# all meta pkgs depend on opaconfig. Remove them first.
	rpm_uninstall_matches("opameta_", "opameta_", "", "");

	# New Uninstall Code
	rpm_uninstall_list("any", "verbose", ("opaconfig") );
	# New Uninstall Code

	system("rm -rf $BASE_DIR/version_wrapper");
	system("rm -rf $BASE_DIR/osid_wrapper");
	# remove the old style version file
	system("rm -rf /$BASE_DIR/version");
	system("rm -rf /sbin/opaconfig");
	# there is no ideal answer here, if we install updates separately
	# then uninstall all with wrapper, make sure we cleanup
	system("rm -rf /sbin/opa_config_ff");
	system("rm -rf /sbin/opa_config_fm");
	system("rm -rf /sbin/opa_config_srp");
	system("rm -rf /sbin/opa_config_vnic");
	system("rm -rf /sbin/opa_config_delta");
	system "rmdir $BASE_DIR 2>/dev/null";	# remove only if empty
	system "rmdir $OPA_CONFIG_DIR 2>/dev/null";	# remove only if empty
	$ComponentWasInstalled{'opaconfig'}=0;
}

my $allow_install;
if ( my_basename($0) ne "INSTALL" )
{
	$allow_install=0;
} else {
	$allow_install=1;
	$FabricSetupScpFromDir="..";
}

sub Usage
{
	if ( $allow_install ) {
		#printf STDERR "Usage: $0 [-r root] [-v|-vv] -R osver -B osver [-d][-t tempdir] [--prefix dir] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n";
		#printf STDERR "               or\n";
		#printf STDERR "Usage: $0 [-r root] [-v|-vv] [-a|-n|-U|-F|-u|-s|-i comp|-e comp] [-E comp] [-D comp] [-f] [--fwupdate asneeded|always] [-l] [--prefix dir] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n";
		#printf STDERR "Usage: $0 [-r root] [-v|-vv] [-a|-n|-U|-F|-u|-s|-i comp|-e comp] [-E comp] [-D comp] [-f] [--fwupdate asneeded|always] [--prefix dir] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n";
		printf STDERR "Usage: $0 [-v|-vv] -R osver [-a|-n|-U|-u|-s|-O|-N|-i comp|-e comp] [-G] [-E comp] [-D comp] [--user-space] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n";
	} else {
#		printf STDERR "Usage: $0 [-r root] [-v|-vv] [-F|-u|-s|-e comp] [-E comp] [-D comp]\n";
#		printf STDERR "          [--fwupdate asneeded|always] [--user_queries|--no_user_queries] [--answer keyword=value]\n";
		printf STDERR "Usage: $0 [-v|-vv] [-u|-s|-e comp] [-E comp] [-D comp]\n";
		printf STDERR "          [--user_queries|--no_user_queries] [--answer keyword=value]\n";
	}
	printf STDERR "               or\n";
	printf STDERR "Usage: $0 -C\n";
	printf STDERR "               or\n";
	printf STDERR "Usage: $0 -V\n";
	if ( $allow_install ) {
		printf STDERR "       -a - install all ULPs and drivers with default options\n";
		printf STDERR "       -n - install all ULPs and drivers with default options\n";
		printf STDERR "            but with no change to autostart options\n";
		printf STDERR "       -U - upgrade/re-install all presently installed ULPs and drivers with\n";
		printf STDERR "            default options and no change to autostart options\n";
		printf STDERR "       -i comp - install the given component with default options\n";
		printf STDERR "            can appear more than once on command line\n";
#		printf STDERR "       -f - skip HCA firmware upgrade during install\n";
		printf STDERR "       --user-space - Skip kernel space and firmware packages during installation\n";
		printf STDERR "            can be useful when installing into a container\n";
		#printf STDERR "       -l - skip creating/removing symlinks to /usr/local from /usr/lib/opa\n";
		printf STDERR "       --without-depcheck - disable check of OS dependencies\n";
		printf STDERR "       --rebuild - force OFA Delta rebuild\n";
		printf STDERR "       --force - force install even if distro don't match\n";
		printf STDERR "                 Use of this option can result in undefined behaviors\n";
		printf STDERR "       -O - Keep current modified rpm config file\n";
		printf STDERR "       -N - Use new default rpm config file\n";

		# -B, -t and -d options are purposely not documented
		#printf STDERR "       -B osver - run build for all components targetting kernel osver\n";
		#printf STDERR "       -t - temp area for use by builds, only valid with -B\n";
		#printf STDERR "       -d - enable build debugging assists, only valid with -B\n";
		printf STDERR "       -R osver - force install for kernel osver rather than running kernel.\n";
	}
#	printf STDERR "       -F - upgrade HCA Firmware with default options\n";
#	printf STDERR "       --fwupdate asneeded|always - select fw update auto update mode\n";
#	printf STDERR "            asneeded - update or downgrade to match version in this release\n";
#	printf STDERR "            always - rewrite with this releases version even if matches\n";
#	printf STDERR "            default is to upgrade as needed but not downgrade\n";
#	printf STDERR "            this option is ignored for interactive install\n";
	printf STDERR "       -u - uninstall all ULPs and drivers with default options\n";
	printf STDERR "       -s - enable autostart for all installed drivers\n";
	printf STDERR "       -e comp - uninstall the given component with default options\n";
	printf STDERR "            can appear more than once on command line\n";
	printf STDERR "       -E comp - enable autostart of given component\n";
	printf STDERR "            can appear with -D or more than once on command line\n";
	printf STDERR "       -D comp - disable autostart of given component\n";
	printf STDERR "            can appear with -E or more than once on command line\n";
	printf STDERR "       -G - install GPU Direct components(must have NVidia drivers installed)\n";
	printf STDERR "       -v - verbose logging\n";
	printf STDERR "       -vv - very verbose debug logging\n";
	printf STDERR "       -C - output list of supported components\n";
#       Hidden feature for internal use
#       printf STDERR "       -c comp - output component information in JSON format\n";
	printf STDERR "       -V - output Version\n";

	printf STDERR "       --user_queries - permit non-root users to query the fabric. (default)\n";
	printf STDERR "       --no_user_queries - non root users cannot query the fabric.\n";
	showAnswerHelp();

	printf STDERR "       default options retain existing configuration files\n";
	printf STDERR "       supported component names:\n";
	printf STDERR "            ";
	ShowComponents(\*STDERR);
	printf STDERR "       supported component name aliases:\n";
	printf STDERR "            opa ipoib mpi psm_mpi verbs_mpi pgas opadev\n";
	if (scalar(@SubComponents) > 0) {
		printf STDERR "       additional component names allowed for -E and -D options:\n";
		printf STDERR "            ";
		foreach my $comp ( @SubComponents )
		{
			printf STDERR " $comp";
		}
		printf STDERR "\n";
	}
	exit (2);
}

my $Default_FirmwareUpgrade=0;	# -F option used to select default firmware upgrade

# translate an ibaccess component name into the corresponding list of OFA comps
# if the given name is invalid or has no corresponding OFA component
# returns an empty list
sub translate_comp
{
	my($arg)=$_[0];
	if ("$arg" eq "opadev") {
		return ( "opa_stack_dev" );
	} elsif ("$arg" eq "opa"){
		return ("oftools","mvapich2_gcc_hfi", "openmpi_gcc_hfi");
	} elsif ("$arg" eq "ipoib"){
		return ( "delta_ipoib" );
	} elsif ("$arg" eq "mpi"){
		return ( "mvapich2_gcc_hfi","openmpi_gcc_hfi");
	} elsif ("$arg" eq "psm_mpi"){
		return ( "mvapich2_gcc_hfi","openmpi_gcc_hfi");
	} elsif ("$arg" eq "delta_mpisrc"){
		return ( "mpisrc" ); # legacy
		# no ibaccess argument equivalent for:
		#	delta_debug
		#
	} else {
		return ();	# invalid name
	}
}

sub process_args
{
	my $arg;
	my $last_arg;
	my $install_opt = 0;
	my $setcomp = 0;
	my $setanswer = 0;
	my $setenabled = 0;
	my $setdisabled = 0;
	my $setosver = 0;
	my $setbuildtemp = 0;
	my $comp = 0;
	my $osver = 0;
	my $setcurosver = 0;
	my $setfwmode = 0;
	my $patch_ofed=0;

	if (scalar @ARGV >= 1) {
		foreach $arg (@ARGV) {
			if ( $setanswer ) {
				my @pair = split /=/,$arg;
				if ( scalar(@pair) != 2 ) {
					printf STDERR "Invalid --answer keyword=value: '$arg'\n";
					Usage;
				}
				set_answer($pair[0], $pair[1]);
				$setanswer=0;
			} elsif ( $setcomp ) {
				foreach $comp ( @Components )
				{
					if ( "$arg" eq "$comp" )
					{
						$Default_Components{$arg} = 1;
						$setcomp=0;
					}
				}
				if ( $setcomp )
				{
					my @comps = translate_comp($arg);
					# if empty list returned, we will not clear setcomp and
					# will get error below
					foreach $comp ( @comps )
					{
						$Default_Components{$comp} = 1;
						$setcomp=0;
					}
				}
				if ( $setcomp )
				{
					printf STDERR "Invalid component: $arg\n";
					Usage;
				}
			} elsif ( $setenabled ) {
				foreach $comp ( @Components, @SubComponents )
				{
					if ( "$arg" eq "$comp" )
					{
						$Default_EnabledComponents{$arg} = 1;
						$setenabled=0;
					}
				}
				if ( $setenabled )
				{
					my @comps = translate_comp($arg);
					# if empty list returned, we will not clear setcomp and
					# will get error below
					foreach $comp ( @comps )
					{
						$Default_EnabledComponents{$comp} = 1;
						$setenabled=0;
					}
				}
				if ( $setenabled )
				{
					printf STDERR "Invalid component: $arg\n";
					Usage;
				}
			} elsif ( $setdisabled ) {
				foreach $comp ( @Components, @SubComponents )
				{
					if ( "$arg" eq "$comp" )
					{
						$Default_DisabledComponents{$arg} = 1;
						$setdisabled=0;
					}
				}
				if ( $setdisabled )
				{
					my @comps = translate_comp($arg);
					# if empty list returned, we will not clear setcomp and
					# will get error below
					foreach $comp ( @comps )
					{
						$Default_DisabledComponents{$comp} = 1;
						$setdisabled=0;
					}
				}
				if ( $setdisabled )
				{
					printf STDERR "Invalid component: $arg\n";
					Usage;
				}
			} elsif ( $setosver ) {
				$Build_OsVer="$arg";
				$setosver=0;
			} elsif ( $setbuildtemp ) {
				$Build_Temp="$arg";
				$setbuildtemp=0;
#			} elsif ( $setfwmode ) {
#				if ( "$arg" eq "always" || "$arg" eq "asneeded") {
#					$Default_FirmwareUpgradeMode="$arg";
#				} else {
#					printf STDERR "Invalid --fwupdate mode: $arg\n";
#					Usage;
#				}
#				$setfwmode = 0;
			} elsif ( $setcurosver ) {
				$CUR_OS_VER="$arg";
				$setcurosver=0;
			} elsif ( "$arg" eq "-v" ) {
				$LogLevel=1;
			} elsif ( "$arg" eq "-vv" ) {
				$LogLevel=2;
#			} elsif ( "$arg" eq "-f" ) {
#				$Skip_FirmwareUpgrade=1;
			} elsif ( "$arg" eq "-i" ) {
				$Default_CompInstall=1;
				$Default_Prompt=1;
				$setcomp=1;
				if ($install_opt || $Default_CompUninstall || $Default_Build) {
					# can't mix -i with other install controls
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "-e" ) {
				$Default_CompUninstall=1;
				$Default_Prompt=1;
				$setcomp=1;
				if ($install_opt || $Default_CompInstall || $Default_Build) {
					# can't mix -e with other install controls
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "-E" ) {
				$Default_Autostart=1;
				$Default_EnableAutostart=1;
				$Default_Prompt=1;
				$setenabled=1;
				if ($Default_Build) {
					# can't mix -E with other install controls
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "-D" ) {
				$Default_Autostart=1;
				$Default_DisableAutostart=1;
				$Default_Prompt=1;
				$setdisabled=1;
				if ($Default_Build) {
					# can't mix -D with other install controls
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "--fwupdate" ) {
				$setfwmode=1;
			} elsif ( "$arg" eq "--answer" ) {
				$setanswer=1;
			} elsif ( "$arg" eq "--without-depcheck" ) {
				$rpm_check_dependencies=0;
			} elsif ( "$arg" eq "--user-space" ) {
				$user_space_only = 1;
			} elsif ( "$arg" eq "--force" ) {
				$Force_Install=1;
			} elsif ( "$arg" eq "-G") {
				if ($HFI2_INSTALL) {
					printf STDERR "Invalid option: $arg not supported in 11.x OPA for HFI2.\n";
					Usage;
				} else {
					$GPU_Install=1;
					$ComponentInfo{"openmpi_gcc_cuda_hfi"}{'Hidden'} = 0;
					$ComponentInfo{"openmpi_gcc_cuda_hfi"}{'Disabled'} = 0;
				}
			} elsif ( "$arg" eq "-C" ) {
				$To_Show_Comps = 1;
			} elsif ( "$arg" eq "-c" ) {
				# undocumented option to output detailed information on a component
				$Default_ShowCompInfo=1;
				$setcomp=1;
			} elsif ( "$arg" eq "-V" ) {
				printf "$VERSION\n";
				exit(0);
			} elsif ( "$arg" eq "-R" ) {
				$setcurosver=1;
			} elsif ( "$arg" eq "-B" ) {
				# undocumented option to do a build for specific OS
				$Default_Build=1;
				$Default_Prompt=1;
				$setosver=1;
				if ($install_opt || $Default_CompInstall || $Default_CompUninstall || $Default_Autostart) {
					# can't mix -B with install
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "-d" ) {
				# undocumented option to aid debug of build
				$Build_Debug=1;
				if ($install_opt || $Default_CompInstall || $Default_CompUninstall || $Default_Autostart) {
					# can't mix -d with install
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "-t" ) {
				# undocumented option to aid debug of build
				$setbuildtemp=1;
				if ($install_opt || $Default_CompInstall || $Default_CompUninstall || $Default_Autostart) {
					# can't mix -t with install
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
			} elsif ( "$arg" eq "--rebuild" ) {
				# force rebuild
				$Build_Force=1;
				$OFED_force_rebuild=1;
			} elsif ( "$arg" eq "--user_queries" ) {
				$Default_UserQueries=1;
			} elsif ( "$arg" eq "--no_user_queries" ) {
				$Default_UserQueries=-1;
			} elsif ( "$arg" eq "--patch_ofed" ) {
				$patch_ofed=1;
			} else {
				# Install options
				if ( "$arg" eq "-a" ) {
					$Default_Install=1;
				} elsif ( "$arg" eq "-u" ) {
					$Default_Uninstall=1;
				} elsif ( "$arg" eq "-s" ) {
					$Default_Autostart=1;
				} elsif ( "$arg" eq "-n" ) {
					$Default_Install=1;
					$Default_SameAutostart=1;
				} elsif ( "$arg" eq "-U" ) {
					$Default_Upgrade=1;
					$Default_SameAutostart=1;
#				} elsif ( "$arg" eq "-F" ) {
#					$Default_FirmwareUpgrade=1;
				} elsif ("$arg" eq "-O") {
					$Default_RpmConfigKeepOld=1;
					$Default_RpmConfigUseNew=0;
				} elsif ("$arg" eq "-N") {
					$Default_RpmConfigKeepOld=0;
					$Default_RpmConfigUseNew=1;
				} else {
					printf STDERR "Invalid option: $arg\n";
					Usage;
				}
				if ($install_opt || $Default_CompInstall
					|| $Default_CompUninstall) {
					# only one of the above install selections
					printf STDERR "Invalid combination of options: $arg not permitted with previous options\n";
					Usage;
				}
				$install_opt=1;
				if ( $Default_RpmConfigKeepOld || $Default_RpmConfigUseNew) {
					$Default_Prompt=0;
				} else {
					$Default_Prompt=1;
				}
			}
			$last_arg=$arg;
		}
	}

	if ($To_Show_Comps == 1) {
		ShowComponents;
		exit(0);
	}
	if ( $setcomp || $setenabled || $setdisabled  || $setosver || $setbuildtemp || $setfwmode || $setanswer) {
		printf STDERR "Missing argument for option: $last_arg\n";
		Usage;
	}
	if ( ($Default_Install || $Default_CompInstall || $Default_Upgrade
			|| $Force_Install)
         && ! $allow_install) {
		printf STDERR "Installation options not permitted in this mode\n";
		Usage;
	}
	if ( ($Default_Build || $OFED_force_rebuild ) && ! $allow_install) {
		printf STDERR "Build options not permitted in this mode\n";
		Usage;
	}
	if ( $patch_ofed) {
		NormalPrint("Patching OFA...\n");
		LogPrint("Executing: cd $ComponentInfo{'opa_stack'}{'SrcDir'}; ./patch_ofed3\n");
		system("cd $ComponentInfo{'opa_stack'}{'SrcDir'}; ./patch_ofed3");
		HitKeyCont;
	}
}

my @INSTALL_CHOICES= ();
sub show_menu
{
	my $inp;
	my $max_inp;

	@INSTALL_CHOICES= ();
	if ( $Default_Install ) {
		NormalPrint ("Installing All OPA Software\n");
		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 1);
	}
   	if ( $Default_CompInstall ) {
		NormalPrint ("Installing Selected OPA Software\n");
		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 1);
	}
  	if ( $Default_Upgrade ) {
		NormalPrint ("Upgrading/Re-Installing OPA Software\n");
		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 1);
	}
#   	if ( $Default_FirmwareUpgrade ) {
#		NormalPrint ("Upgrading HCA Firmware\n");
#		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 4);
#	}
   	if ($Default_Uninstall ) {
		NormalPrint ("Uninstalling All OPA Software\n");
		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 6);
	}
   	if ($Default_CompUninstall ) {
		NormalPrint ("Uninstalling Selected OPA Software\n");
		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 6);
	}
   	if ($Default_Autostart) {
		NormalPrint ("Configuring autostart for Selected installed OPA Drivers\n");
		@INSTALL_CHOICES = ( @INSTALL_CHOICES, 3);
	}
	if (scalar(@INSTALL_CHOICES) > 0) {
		return;
	}
	system "clear";
	printf ("$BRAND OPA $VERSION Software\n\n");
	if ($allow_install) {
		printf ("   1) Install/Uninstall Software\n");
	} else {
		printf ("   1) Show Installed Software\n");
	}
	printf ("   2) Reconfigure $ComponentInfo{'delta_ipoib'}{'Name'}\n");
	printf ("   3) Reconfigure Driver Autostart \n");
	printf ("   4) Generate Supporting Information for Problem Report\n");
	printf ("   5) FastFabric (Host/Chassis/Switch Setup/Admin)\n");
#	printf ("   6) Update HCA Firmware\n");
	$max_inp=5;
	if (!$allow_install)
	{
#		printf ("   7) Uninstall Software\n");
		printf ("   6) Uninstall Software\n");
		$max_inp=6;
	}
	printf ("\n   X) Exit\n");

	while( $inp < 1 || $inp > $max_inp) {
		$inp = getch();

		if ($inp =~ /[qQ]/ || $inp =~ /[Xx]/ ) {
			return 1;
		}
		if ($inp =~ /[0123456789abcdefABCDEF]/)
		{
			$inp = hex($inp);
		}
	}
	@INSTALL_CHOICES = ( $inp );
	return 0;
}

determine_os_version;
init_components;

# when this is used as main for a component specific INSTALL
# the component can provide some overrides of global settings such as Components
overrides;

process_args;
check_root_user;
if ( $Default_ShowCompInfo )
{
        ShowCompInfo();
        exit(0);
}
if ( ! $Default_Build ) {
	open_log("");
} else {
	open_log("./build.log");
}

if ( ! $Default_Build ) {
	verify_modtools;
	if ($allow_install) {
		verify_distrib_files;
	}
}

set_libdir;
init_delta_info($CUR_OS_VER);

do{
	if ($Default_Build) {
		$exit_code = build_all_components($Build_OsVer, $Build_Debug, $Build_Temp, $Build_Force);
		done();
	} else {
		if ( show_menu != 0) {
		done();
		}
	}

	foreach my $INSTALL_CHOICE ( @INSTALL_CHOICES )
	{
		if ($allow_install && $INSTALL_CHOICE == 1)
		{
			select_debug_release(".");
			show_install_menu(1);
			if ($Default_Prompt) {
				if ($exit_code == 0) {
					print "Done Installing OPA Software.\n"
				} else {
					print "Failed to install all OPA software.\n"
				}
			}
		}
		elsif ($INSTALL_CHOICE == 1) {
			show_installed(1);
		}
		elsif ($INSTALL_CHOICE == 6)
		{
			show_uninstall_menu(1);
			if ( $Default_Prompt ) {
				if ($exit_code == 0) {
					print "Done Uninstalling OPA Software.\n"
				} else {
					print "Failed to uninstall all OPA Software.\n"
				}
			}
		}
		elsif ($INSTALL_CHOICE == 2)
		{
			Config_ifcfg(1,"$ComponentInfo{'delta_ipoib'}{'Name'}","ib", "$FirstIPoIBInterface",1);
			check_network_config;
		}
		elsif ($INSTALL_CHOICE == 3)
		{
			reconfig_autostart;
			if ( $Default_Prompt ) {
				print "Done OPA Driver Autostart Configuration.\n"
			}
		}
		elsif ($INSTALL_CHOICE == 4)
		{
			# Generate Supporting Information for Problem Report
			capture_report($ComponentInfo{'oftools'}{'Name'});
		}
		elsif ($INSTALL_CHOICE == 5)
		{
			# FastFabric (Host/Chassis/Switch Setup/Admin)
			run_fastfabric($ComponentInfo{'fastfabric'}{'Name'});
		}
	}
}while( !$Default_Prompt );
done();
sub done() {
	if ( not $user_space_only ) {
		do_rebuild_ramdisk;
	}
	close_log;
	exit $exit_code;
}
