#!/usr/bin/perl
############################################################################
#
# sap_suse_cluster_connector
#
# Author:  fabian.herschel@suse.com
# (c) 2010-2014 SUSE Linux Products GmbH, Nuremberg, Germany
# (c) 2015-2018 SUSE Linux GmbH, Nuremberg, Germany
# (c) 2019-2020 SUSE LLC
# License: GPLv2 or later
#
############################################################################
#
# REMARKS:
#    we need record pending activated to be able to catch pending actions
#    op_defaults $id="op_defaults-options" record-pending="true"
#
# TODOs:
#    TODO: testing, testing, testing
#    TODO: long cmd names (like check_pending_action)
#    TODO: Could we check for the record-pending option?
#    TODO: database instances -> lsr --sid SID --dbhost HOST --dbtype TYPE
#

use Getopt::Long;
use Sys::Hostname;
use Sys::Syslog;
use strict;
use File::Temp qw/ tempfile tempdir /;

my $DEBUG; my $filename;
my $nowstring;
#
# init some environment
#

my $cmd_crm = "crm";
my $cmd_crm_resource = "crm_resource";
my $cmd_ptest = "crm_simulate";
my $logident = "sap_suse_cluster_connector";
my $logoptions = "pid";
my $logfacility = "LOG_USER";
my $protocolVersion=3;
my $version="3.1.2";
my $haProd="SLE HAE";
my $haProdSAP="sap_suse_cluster_connector";
my $haProdSAPCon="sap_suse_cluster_connector";
my $haProdDoc="https://www.suse.com/products/sles-for-sap/resource-library/sap-best-practices/";
#
# open syslog
#
openlog($logident, $logoptions, $logfacility);
my @all_cmds = ($cmd_crm, $cmd_crm_resource, $cmd_ptest);

#	printf "ARGV: %s\n", join(" ", @ARGV);
sub usage() {
printf "$0 --help
$0 cmd options
      where cmd could be:
      help
      init
      cpa --res RES --act ACT
      fra --res RES --act ACT  [ --node NODE ]
      gvi --out FILE
      hcc --out FILE --sid SID --ino INSTNO
      lsr --out FILE --sid SID --ino INO | --dbhost HOST --dbtype TYPE
      lsn --out FILE --res RES
      smm --out FILE --sid SID --ino INSTNO --mod NMODE
";
}

sub paramproblem() {
	syslog("LOG_ERR", "called with wrong parameters");
	usage();
	exit(2);
}

sub checkavail(@) {
	my @CHECK = @_;
	my $chk;
	my $rc=1;
	for $chk ( @CHECK ) {
		if ( ! ( defined ( $chk )))  {
			$rc=0;
		}
	}
	return $rc;
}

sub initial_check() {
	my $rc=0;
	my $check_cmd;
	#
	# move old log file to *.old in cwd which is /usr/sap/<SID>/<INST>/work
	#
	rename("$logident" . ".log", "$logident" . ".old");
	#
	# open new log file in cwd which is /usr/sap/<SID>/<INST>/work
        #
	#($DEBUG, $filename) = tempfile("sap_suse_cluster_conector.XXXXX", SUFFIX => '.log');
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	printf "\n---------------------------------------------------\n";
	printf "trc file: %s\n", $logident . ".log";
	printf "---------------------------------------------------\n";
	$nowstring = localtime;
	printf "%s : init()\n", $nowstring;
	for $check_cmd ( @all_cmds) {
#		if ( -e "/usr/bin/$check_cmd" ) {
#			printf "INFO: %s available", $check_cmd;
#		} else {
#			printf "ERR: Cluster command %s missing\n", $check_cmd;
#			$rc=3;
#		}
	}
	return $rc;
}

sub fire_resource_action {
	my ($rsc, $act, $nod) = @_;
	my $rc=0;
	$nowstring = localtime;
	printf "%s : fra($rsc, $act, $nod)\n", $nowstring;
	if ( $act eq "stop" ) {
		syslog("LOG_INFO", "fire_resource_action stop %s\n", $rsc);
		if (system($cmd_crm,"resource",$act,$rsc)) { $rc=1; }
	} elsif ( $act eq "start" ) {
		syslog("LOG_INFO","fire_resource_action start %s\n", $rsc);
		if (system($cmd_crm,"resource",$act,$rsc) ) { $rc=1; }
	} elsif ( $act eq "migrate" || $act eq "move" ) {
		syslog("LOG_INFO","fire_resource_action %s %s %s\n", $act, $rsc, $nod);
		if ( defined $nod ) {
			if (system($cmd_crm,"resource","move",$rsc,$nod, "PT5M","force"   ) ) { $rc=1; }
		} else {
			if (system($cmd_crm,"resource","move",$rsc,"PT5M","force") ) { $rc=1; }
                }
	}
	syslog("LOG_INFO"," rc=%i\n", $rc);
	return $rc;
}

sub check_pending_action {
	my ($res, $act, $sta) = @_;
	my $rc=0;
	$nowstring = localtime;
	printf "%s : cpa($res, $act, $sta)\n", $nowstring;
	#
	# rc:
	#     0: found
	#     1: not found
        #     2: internal error
	$rc=1;
	#
	# rsc_ip_NA1_sapna1as     (ocf::heartbeat:IPaddr2) Started : rsc_ip_NA1_sapna1as_start_0 (node=node0101, call=16, rc=0): complete
        # rsc_sap_NA1_ASCS00_sapna1as:0   (ocf::heartbeat:SAPInstance) Stopped : rsc_sap_NA1_ASCS00_sapna1as:0_monitor_0 (node=node0102, call=11, rc=7): complete
        # rsc_sap_NA1_ASCS00_sapna1as:0   (ocf::heartbeat:SAPInstance) Slave : rsc_sap_NA1_ASCS00_sapna1as:0_start_0 (node=node0101, call=-1, rc=14): pending
        # rsc_sap_NA1_ASCS00_sapna1as:0   (ocf::heartbeat:SAPInstance) Master : rsc_sap_NA1_ASCS00_sapna1as:0_demote_0 (node=node0101, call=-1, rc=14): pending
        # rsc_sap_HA0_D02 (ocf::heartbeat:SAPInstance) Started  FAILED: rsc_sap_HA0_D02_start_0 (node=cl2n01, call=-1, rc=14): pending<---- FOUND!!
        #
	#    crm_resource -O -r $rsc | grep "${rsc}_${act}_.*: ${sta}"  && rc=0
	#open CRMOUT, "$cmd_crm_resource -O -r $res 2>/dev/null |" or $rc=2;
	open CRMOUT, "$cmd_crm_resource -O 2>/dev/null |" or $rc=2;
	printf "<--------- cpa ------>\n";
	while (<CRMOUT>) {
		chomp;
		my $line = $_;
		printf "%s", $line;
		# if ( $line =~ /${res}_${act}_.*: ${sta}/ ) { # FH 2012-01-05: Changed to find also clones and master-slaves
		#if ( $line =~ /${res}(:[0-9]+_|_)${act}_.*: ${sta}/ ) {
		#if ( $line =~ /${res}.*: ${sta}/ ) {
		my ${masteract};
		if ( ${act} eq "stop" ) {
			$masteract="demote";
		} elsif ( ${act} eq "start" ) {
                        $masteract="promote";
                }
		#if ( $line =~ /(${res}(:[0-9]+)?_(${act}|${masteract})_0.*: ${sta})/ ) {
		if ( $line =~ /(${res}(:[0-9]+)?_(${act}|demote|promote)_0.*: ${sta})/ ) {
			$rc=0;
			syslog("LOG_INFO","Pending action %s for %s found", $1, ${res});
			printf "<---- FOUND!!";
		}
		printf "\n";
	}
        close CRMOUT;
	if ( $rc != 0 ) {
           open CRMOUT, "$cmd_crm_resource --resource ${res} --get-parameter target-role --meta 2>/dev/null |" or $rc=2;
           while (<CRMOUT>) {
                chomp;
                my $line = $_;
                printf "%s", $line;
		if ( (${act} eq "stop") && ( $line =~ "Stopped" )) {
			$rc=0;
			syslog("LOG_INFO","target-role stopped for resource %s found", ${res});
		}
		if ( (${act} eq "start") && ( $line =~ "Started" )) {
			syslog("LOG_INFO","target-role started for resource %s found", ${res});
			$rc=0;
		}
	   }
        }
	close CRMOUT;
        #
        #### BY_PASS_CODE
        #if ( $rc != 0 ) {
	#	syslog("LOG_INFO","SENDING PENDING ACTION FOUND TO DEBUG");
	#	$rc=0;
        #}
	printf "</--------- cpa ------>\n";
	return $rc;
}

sub get_resource_and_status {
    #
    # find _local_ resources matching the SAP SID/INO
    # TODO: currently we find all resources not only 'local' ones
    #
    # input params are:
    #   SID InstanceNumber
    #
    # return a hash struct with fields
    #    resource_name: primitive name of the resource
    #    group_name:    group or clone set name (optional)
    #    maintenance: maintenance mode of the resource
    #    isManaged:  is-manged mode if the resource
    #    maintenanceMode: maintenance mode of the CLUSTER
    #
    my ($sid, $ino) = @_;
    my %result;

    my $resource_name="";
    my $group_name="";
    my $maintenance="";
    my $isManaged="";
    my $maintenanceMode="";

    my $foundRes=0;
    my $finstance="";

	my ($sclass, $sprovider, $sra, $sparam, $sparam2 ) = ("ocf", "heartbeat", "SAPInstance", "InstanceName", "ERS_InstanceName");

    open CRMOUT, "$cmd_crm configure show 2>/dev/null |" || die "could not open crm output";
    my $line;
    while (defined($line = <CRMOUT>) ) {
        #
        # to handle line continuation ...
        chomp $line;
        if ($line =~ s/\\$//) {
            $line .= <CRMOUT>;
            redo unless eof(CRMOUT);
        }
        chomp $line;
        #syslog ("LOG_DEBUG", "%s\n", $line);
        #
        # handle properties
        #
        if ( $line =~ /^property .*maintenance-mode=true/ ) {
            $maintenanceMode = "true";
        }
        #
        # handle primitive records
        #
        if ( ($foundRes==0) && ( $line =~ /^primitive ([a-zA-Z0-9_-]+) ($sclass:$sprovider:|)($sra)/ )) {
            #
            # 1. found begin of primitive definition and we did not already found the resource
            #   -> catch resource-name, resource-class, resource-provider, resource-agent
            # 2. we have found a primitive of the correct type, lets look at the (ERS_)InstanceName
            #
            my $curr_resource=$1;
            #
            #
            #syslog("LOG_DEBUG","rsc: %s\n", $line);
            my $searchInst = "${sid}_[a-zA-Z0-9]+${ino}_[a-zA-Z0-9_-]+";
            if (  $line =~ /(ERS_)?InstanceName="?($searchInst)"?/ ) {
                my $isERS=$1;
                my $finstance=$2;
                $resource_name = $curr_resource;
                $foundRes=1;
                if ( ! defined $isERS ) { $isERS="" };
                syslog("LOG_DEBUG","Resource %s with %sInstanceName=%s found\n", $resource_name, $isERS, $finstance);
                #
                # check, if the resource is managed
                #
                if (  $line =~ /is-managed="?false"?/ )  {
                    syslog("LOG_DEBUG","Resource %s found but unmanged", $resource_name);
                    $isManaged="false";
                } else {
                    $isManaged="true";
                }
                #
                # check, if the resource is in maintenance
                #
                if (  $line =~ /maintenance="?true"?/ )  {
                    syslog("LOG_DEBUG","Resource %s found but in maintenance", $resource_name);
                    $maintenance="true";
                } else {
                    $maintenance="false";
                }
            }
        } elsif ( ($foundRes==1) && ( $line =~ /^(group|ms) ([a-zA-Z0-9_-]+).*($resource_name)/ )) {
            #
            # found resource is member of a group
            #
            my $ftype=$1;
            $group_name = $2;
            if (  $line =~ /is-managed="?false"?/ )  {
                syslog("LOG_DEBUG", "%s %s with primitive %s is unmanged", $ftype, $group_name, $resource_name);
                # TODO: Use different attribute as for primitive?
                    $isManaged="false";
                } else {
                    $isManaged="true";
                }
        }
    }
    $result{resource_name}=$resource_name;
    $result{group_name}=$group_name;
    $result{maintenance}=$maintenance;
    $result{isManaged}=$isManaged;
    $result{maintenanceMode}=$maintenanceMode;
    return %result;
}

sub list_sap_resources {
	#
	# --out file --sid sid --ino ino
	#
	my ($out, $sid, $ino) = @_;
	my $rc=1;
	$nowstring = localtime;
	printf "%s : lsr($out, $sid, $ino)\n", $nowstring;
	# TODO: implement action
	#
	# typical crm syntax/output:
	# primitive rsc_SAPInstance_NA0_ASCS00_sapna0as ocf:heartbeat:SAPInstance \
	#        params InstanceName="NA0_ASCS00_sapna0as" AUTOMATIC_RECOVER="true" START_PROFILE="/usr/sap/NA0/SYS/profile/START_ASCS00_sapna0as" \
	#        op monitor interval="120s" timeout="60s" start_delay="120s" \
	#        op start interval="0" timeout="120s" \
	#        op stop interval="0" timeout="180s" on_fail="block" \
	#        meta target-role="Stopped" maintenance=true is-managed=true
	#
	# TODO: we might also need to check param  ERS_/InstanceName
	#
	#use IO::Handle;

	#my ($out, $sid, $ino ) = @ARGV;

	$ENV{'PATH'} = $ENV{'PATH'} . ":/usr/sbin:/sbin";
	#printf "LSR\n";
	#printf "PARAMS: (out, sid, ino) = ( %s, %s, %s)\n", $out, $sid, $ino ;
	#printf "ARGV: %s", join(" ", @ARGV);

	#my ($fra, $fname, $fgname) = ("","","","","");
	my $foundRes = 0; # found correct Resource

    my %sapResource;

    %sapResource = get_resource_and_status($sid, $ino );

    my $resource_name = $sapResource{resource_name};
    my $group_name = $sapResource{group_name};
    my $isManaged = $sapResource{isManaged};
    my $maintenance = $sapResource{maintenance};
    my $maintenanceMode = $sapResource{maintenanceMode};

    if ($resource_name ne "" ) {
        $foundRes = 1;
		if ($out eq "") {
			printf "%s:%s:%s\n", $resource_name, $group_name, "-";
			$rc=0;
		} else {
			open OUT, ">" . $out;
			syslog("LOG_INFO","lsr result: %s:%s:%s:%s:%s\n", $sid, $ino, $resource_name, "", "");
			printf OUT "%s:%s:%s:%s:%s\n", $sid, $ino, $resource_name, "", "";
			close OUT;
			$rc=0;
		}
    }

    if (($foundRes==1) && (( $isManaged eq "false" ) || ( $maintenance eq "true" ) || ( $maintenanceMode eq "true" ))) {
        $rc=3;
    }

	# TODO: scores and node names sorted by scores -> use ptest
	#
	#ls3198:/usr/lib/ocf/resource.d/heartbeat # ptest -Ls | grep ls3199 | egrep '(rsc_SAPInstance_NA0_ASCS00_sapna0as|grp_sap_NA0)'
	#group_color: grp_sap_NA0 allocation score on ls3199: 0
	#group_color: rsc_SAPInstance_NA0_ASCS00_sapna0as allocation score on ls3199: 0
	#native_color: rsc_SAPInstance_NA0_ASCS00_sapna0as allocation score on ls3199: -INFINITY
	return $rc;
}

sub list_sap_nodes {
	#
        # --out file --res RES
	#
	###########################################
	# return codes
	#   0: everything worked fine
	#   1:
	#   2: internal error
	#
	my ($outfile, $resource) = @_;
	my $rc=0;
	$nowstring = localtime;
	printf "%s : lsn($outfile, $resource)\n", $nowstring;
	# TODO: check implemented action
	###############################################################################################
	#
	# 1. GET HOSTNAME WHERE FUNCTION WAS CALLED
	#
	my $myhostname = hostname;
	#
	##########################
	#
	# 2. GET NODE NAME, WHERE RESOURCE IS CURRENTLY RUNNING
	#
	# to get the current location of the resource in the cluster, lets ask the cluster itself ;-)
	# we assume to get an answer in the following format:
	#
	# resource RES is running on: NODE
	#
	open CRMRES, "$cmd_crm_resource -W -r $resource|";
	my $crm_res_location_in = <CRMRES>;
	chomp $crm_res_location_in;
	#printf "DBG: where-result: %s\n", $crm_res_location_in;
	my $current_node="";
	if ( $crm_res_location_in =~ /^resource\s+(\S)+\sis running on:\s+(\S+)\s*/ ) {
		#printf "DBG: where-result: match\n";
		$current_node = $2;
	}
	close CRMRES;
	#
	##########################
	#
	# 3. GET ORDERED LIST OF CLUSTER NODES WHICH COULD RUN THE RESOURCE
	#
	my $node_list="";
	my %resource;
	open PTEST, "$cmd_ptest -Ls |" || return 2;
	#
	# we rely on the following format:
	#
	#   ...
	#   group_color: RSC allocation score on NODE: VALUE
	#   ...
	#   native_color: RSC allocation score on NODE: VALUE
	#
	while (<PTEST>) {
		chomp;
		# printf "%s\n", $_;
		if ( /^([^:]+):\s*(\S+)\s+allocation score on\s+(\S+):\s+(.*)$/ ) {
			# printf STDERR "DBG: call: %s res: %s, node: %s, score: %s\n", $1, $2, $3, $4;
			$resource{$2}->{nodes}->{$3}->{gc}=$4;
			push(@{$resource{$2}->{priorities}->{$4}}, $3);
		}
	}
	close PTEST;
	#
	# get sorted list of scores (excluding -INFINITY)
	#
	my @filtered_prios=grep (!/-INFINITY/, keys (%{$resource{$resource}->{priorities}}));
	@filtered_prios=sort {$b <=> $a} @filtered_prios; # reverse order
	#
	# figure out node list sorted by prios (scores)
	#
	my $prio;
	my $node;
	my @nodes;
	my %node_mark;
	for $prio ( @filtered_prios ) {
		#printf "for prio %s checking nodes %s\n", $prio, join " ",@{$resource{$resource}->{priorities}->{$prio}};
		for $node ( @{$resource{$resource}->{priorities}->{$prio}} ) {
			if ( ! defined ( $node_mark{$node} )) {
				#printf "DBG: for prio %s adding node %s\n", $prio, $node;
				$node_mark{$node}=1;
				push(@nodes, $node);
			}
		}
	}
	$node_list = join ",", @nodes;
	#
	# SOME MORE DBG
	#
	#my @allnodes=keys(%{$resource{$resource}->{nodes}});
	#printf "DBG: %s all nodes: %s\n", $resource, join(",", @allnodes);
	#printf "DBG: %s prios: %s\n", $resource, join(" ", @filtered_prios);
	#printf "DBG: %s ordered nodes %s\n", $resource, join(" ", @nodes);
	#
	# RESULT
	#
	if ( $outfile ne "" ) {
		open OUTFILE, ">$outfile";
		syslog("LOG_INFO","lsn result: %s:%s:%s:%s\n",  $resource, $myhostname, $current_node, $node_list);
		printf OUTFILE "%s:%s:%s:%s\n",  $resource, $myhostname, $current_node, $node_list;
		close OUTFILE;
	} else {
		printf "%s:%s:%s:%s\n",  $resource, $myhostname, $current_node, $node_list;
	}
	return $rc;
}

sub get_version_info($)
{
    my ($outfile, $resource) = @_;
    my $rc=0;
    $nowstring = localtime;
    printf "%s : gvi($outfile, $resource)\n", $nowstring;
    if ( $outfile ne "" ) {
        #HASCRIPTCO-VERS
        #HAPROD
        #HAPROD-SAP
        #HAPROD-DOC
	open OUTFILE, ">$outfile";
	syslog("LOG_INFO", "gvi result: %s\n%s\n%s (%s %s)\n%s\n",  $protocolVersion, $haProd, $haProdSAP, $haProdSAPCon, $version, $haProdDoc);
	printf OUTFILE "%s\n%s\n%s (%s %s)\n%s\n",  $protocolVersion, $haProd, $haProdSAP, $haProdSAPCon, $version, $haProdDoc;
	close OUTFILE;
    } else {
	printf "%s\n%s\n%s (%s %s)\n%s\n",  $protocolVersion, $haProd, $haProdSAP, $haProdSAPCon, $version, $haProdDoc;
    }
    return $rc;
}

sub ha_config_check($$$)
{
    # output-multiple lines, each line formatted as: CHK-STATE:CHK-CATEGORY:CHK-DESCRIPTION:CHK-COMMENT
    #
    my $rc=0;
    my ($out, $sid, $ino) = @_;
    $nowstring = localtime;
    printf "%s : hcc($out, $sid, $ino)\n", $nowstring;
    if ( $out ne "" ) {
        syslog("LOG_INFO", "hcc run_checks");
	system("bash","/usr/share/sap_suse_cluster_connector/run_checks","$out","$sid", "$ino");
        $rc=0;
    } else {
        syslog("LOG_INFO", "hcc run_checks stdout");
	system("bash","/usr/share/sap_suse_cluster_connector/run_checks","$out","$sid", "$ino");
        $rc=0;
    }
    return $rc;
}

sub set_maintenance_mode {
    my $rc=0;
    my $mm=0;
    my ($out, $sid, $ino, $nmode) = @_;
    $nowstring = localtime;
    printf "%s : smm($out, $sid, $ino, $nmode)\n", $nowstring;

    my %sapResource;

    %sapResource = get_resource_and_status($sid, $ino );

    my $resource_name = $sapResource{resource_name};
    my $group_name = $sapResource{group_name};
    my $isManaged = $sapResource{isManaged};
    my $maintenance = $sapResource{maintenance};
    my $maintenanceMode = $sapResource{maintenanceMode};

    if (($resource_name ne "") && ( $maintenance eq "true" )) {
        # 1 (maintenance mode is active)
        # printf("set_maintenance_mode: mm=1 - maintenance mode is active\n");
        $mm=1;
    } elsif (($resource_name ne "") && (( $maintenance eq "" ) || ( $maintenance eq "false" ))) {
        # 0 (maintenance mode is inactive)
        # printf("set_maintenance_mode: mm=0 - maintenance mode is inactive\n");
        $mm=0;
    } else {
        # 2 (maintenance mode is divergent)
        # printf("set_maintenance_mode: mm=2 - maintenance mode is divergent\n");
        $mm=2;
    }

    if ( $out ne "" ) {
        open OUTFILE, ">$out";
        printf OUTFILE "%s\n", $mm ;
        close OUTFILE;
    } else {
        printf "DEBUG- MODE $mm\n" ;
    }
    #
    # optionally set the maintenance mode
    #
    if ( $nmode eq "1" ) {
        # smm active
        # crm configure property maintenance-mode=true
        # crm_resource --resource rsc_sap_EN2_ASCS00 --meta --set-parameter=maintenance --parameter-value true
        system($cmd_crm_resource, "--resource", $resource_name, "--meta", "--set-parameter=maintenance", "--parameter-value", "true");
        $rc=0;
    } elsif ( $nmode eq "0" ) {
        # crm_resource --resource rsc_sap_EN2_ASCS00 --meta --set-parameter=maintenance --parameter-value false
        system($cmd_crm_resource, "--resource", $resource_name, "--meta", "--set-parameter=maintenance", "--parameter-value", "false");
        $rc=0;
    } else {
        $rc=0;
    }
    printf "set_maintenance_mode: rc=%s\n", $rc;
    return $rc;
}

sub initialize($)
{
    my ($refSC)= @_;
    open BASEPRODUCT, "</etc/products.d/baseproduct" or syslog("LOG_INFO", "open /etc/products.d/baseproduct failed");
#
# <summary>...</summary>  -> HA_PRODUCT, HA_PRODUCT_SAP
         while (<BASEPRODUCT>) {
             chomp;
             my $line = $_;
             if ($line =~ /<summary>(.+)<\/summary>/ ) {
                 $$refSC{"HA_PRODUCT"}=$1;
                 $$refSC{"HA_PRODUCT_SAP"}=$1;
             }
         }

    close BASEPRODUCT;
}

#
# "main"
#
my ($cmd) = @ARGV; shift;
my $result=2;
my ($sid, $ino, $act, $out, $res, $nod, $sta, $nmode);
my $return_code=2;
$ENV{'PATH'} = $ENV{'PATH'} . ":/usr/sbin:/sbin";

if ( $cmd eq "h" || $cmd eq "help" ||  $cmd eq "--help" ) {
	 usage();
	 exit 0;
}

my %SC;
initialize(\%SC);
if ( defined $SC{"HA_PRODUCT"} ) { $haProd=$SC{"HA_PRODUCT"}; }
if ( defined $SC{"HA_PRODUCT_SAP"} ) { $haProdSAP=$SC{"HA_PRODUCT_SAP"}; }
if ( defined $SC{"HA_PRODUCT_URL"} ) { $haProdDoc=$SC{"HA_PRODUCT_URL"}; }

if  ($cmd eq "init")  {
	syslog("LOG_INFO", "init call");
	$return_code=initial_check();
} elsif ( $cmd eq "cpa" ) {
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	$result = GetOptions ("res=s" => \$res,
	                   "act=s" => \$act,
		 ) &&
	checkavail(($res, $act)) || paramproblem();
	syslog("LOG_INFO", "cpa call (res=%s,act=%s)", $res, $act);
	$return_code=check_pending_action($res, $act, "[Pp]ending"); #bsc1244439 - pacemaker-cli 3.0.x now could also be "Pending" instead of "pending"
} elsif ( $cmd eq "fra" ) {
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	 #
	 # DONE: don't check if node is set - as it is optional
	 #
	$nod = "";
	$result = GetOptions ("res=s" => \$res,
	                   "act=s" => \$act,
                           "node:s" => \$nod,
		 ) &&
	checkavail(($res, $act)) || paramproblem();
	syslog("LOG_INFO", "fra call (res=%s,act=%s,nod=%s)", $res, $act, $nod);
	$return_code=fire_resource_action($res, $act, $nod);
} elsif ( $cmd eq "gvi" ) {
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	$result = GetOptions ("out=s" => \$out,
		 ) &&
	checkavail(($out)) || paramproblem();
	# TODO: action
	syslog("LOG_INFO", "gvi call (out=%s)", $out);
	$return_code=get_version_info($out);
} elsif ( $cmd eq "hcc" ) {
    open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	$result = GetOptions ("sid=s" => \$sid,
	                   "ino=s" => \$ino,
	                   "out=s" => \$out,
		 ) &&
	checkavail(($sid, $ino, $out)) || paramproblem();
	# TODO: action
	syslog("LOG_INFO", "hcc call (out=%s)", $out);
	$return_code=ha_config_check($out,$sid,$ino);
} elsif ( $cmd eq "lsn" ) {
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	$result = GetOptions ("out=s" => \$out,
	                   "res=s" => \$res,
		 ) &&
	checkavail(($res, $out)) || paramproblem();
	# TODO: action
	syslog("LOG_INFO", "lsn call (out=%s,res=%s)", $out, $res);
	$return_code=list_sap_nodes($out, $res);
} elsif ( $cmd eq "lsr" ) {
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	$result = GetOptions ("sid=s" => \$sid,
	                   "ino=s" => \$ino,
	                   "out=s" => \$out,
		 ) &&
	checkavail(($sid, $ino, $out)) || paramproblem();
	syslog("LOG_INFO", "lsr call (out=%s,sid=%s,ino=%s)", $out, $sid, $ino);
	$return_code=list_sap_resources($out, $sid, $ino);
} elsif ( $cmd eq "smm" ) {
        open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	$result = GetOptions ("sid=s" => \$sid,
	                   "ino=s" => \$ino,
	                   "out=s" => \$out,
	                   "mod=s" => \$nmode,
		 ) &&
	checkavail(($sid, $ino, $out)) || paramproblem();
	# TODO: action
	syslog("LOG_INFO", "smm call (out=%s,ino=%s,sid=%s,mod=%s)", $out,$sid,$ino,$nmode);
	$return_code=set_maintenance_mode($out, $sid, $ino, $nmode);
	 # smm --out FILE --sid SID --ino INSTNO --mod NMODE
} else  {
	open($DEBUG, ">>$logident" . ".log");
	*STDOUT=*$DEBUG;
	 #
	 # remark: found no or unknown cmd
	 #
	$nowstring = localtime;
	printf "%s : unkown function %s\n", $nowstring, $cmd;
 	paramproblem()
}

closelog();
exit $return_code;
#
#################################################################
