#!/bin/bash -p
# rbsaudit v1.6 2013-08-04 , Finn Magnusson, finn.magnusson@ericsson.com
# Type "rbsaudit" for help.

###########################################################################################
# Pathes to files:
###########################################################################################
moshelldir=`dirname "$0"`
if [[ $moshelldir != /* ]] ; then moshelldir=`pwd`/$moshelldir ; fi
logdir="$moshelldir/logfiles/logs_rbsaudit"
vobsinstallation=0
unamea=$(uname -a)
gawkext=""
gawklib=""
if [[ $unamea = [Ll][iI][nN][uU][xX]*x86_64* ]] ; then gawklib="lin64"   ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".lin64" ; fi
elif [[ $unamea = [Ll][iI][nN][uU][xX]* ]]      ; then gawklib="linux"   ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".linux" ; fi
elif [[ $unamea = SunOS*sparc* ]]               ; then gawklib="solaris" ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".solaris" ; fi
elif [[ $unamea = SunOS* ]]                     ; then gawklib="sol86"   ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".sol86" ; fi
else gawklib="cygwin" ; gawkext=".exe"
fi
gawkprog="gawk${gawkext}" 
gawk="$moshelldir/$gawkprog"
#special case where moshell has been installed on a linux 32 bit machine but should be run on linux 64 sharing the same file system
if [[ $unamea = [Ll][iI][nN][uU][xX]*x86_64* && $vobsinstallation != 1 && `file "$moshelldir/gawk"` = *32-bit* ]] ; then gawklib="linux" ; fi
filefunc="$moshelldir/commonjars/lib/${gawklib}/filefuncs"
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}$moshelldir/commonjars/lib/${gawklib}
export LANG=C
export LC_ALL=C

defLogDir=$moshelldir/commonjars/defLogDir.sh
temp_logdir=$($defLogDir rbsaudit)
if [[ -w $temp_logdir && -d $temp_logdir ]] ; then logdir=$temp_logdir ; fi
###########################################################################################

###########################################################################################
#  Specify how the cabinets are cabled, for each cabinet type (3101 and 3202).
#  Cabling=1 means that: sector1 is connected to feeder/jumper cables 1 and 2, sector2 to cables 3 and 4, and sector3 to cables 5 and 6.
#  Cabling=2 means that: sector1 is connected to feeder/jumper cables 1 and 4, sector2 to cables 2 and 5, and sector3 to cables 3 and 6.
###########################################################################################
cabling_3202=1
cabling_3101=2

###########################################################################################
#  List of MO/Attributes that shouldn't be included in corrective command files
#  eg, attributes that are restricted, or read-only
###########################################################################################
exclude_from_set_commands=$(cat <<EOF
AntennaBranch,verticalAntennaTilt
AntennaBranch,mechanicalAntennaTilt
AntennaBranch,antennaType
EOF)
###########################################################################################

function print_usage()
{
cat <<EOF
***************
Command syntax:
***************
  rbsaudit <Option(s)> <Argument>

********
Options:
********
  -b <baseline_file>	
Where <baseline_file> is a parameter list derived from Winnow database.
See example in moshell/examples/audit_files/baseline.txt
This file can be directly exported from the following excel documents:
	n/19059-HSD10102/m,  where: 
	n=3 for RNC      m=3 for P3 
	n=4 for RBS      m=4 for P4 
	n=5 for RXI      m=5 for P5
  -c <cdr_file>	
Where <cdr_file> is a file containing rbs data (sector, antenna, feeders, etc.)
See example in moshell/examples/audit_files/CDR_celldata.txt

*********
Argument:
*********
  - directory containing the modumps. Modumps should be taken with mobatch, using command:
mobatch <rbs_sitefile> 'lt ^(Sector|AntJumperCable|AntFeederCable|NodeBFunction|AntennaBranch|aal2pathvcctp)$;get'
Type "mobatch" at unix prompt for more info on how to use mobatch.

********
Example:
********
  >> rbsaudit -b ./examples/audit_files/baseline.txt \\
  	      -c ./examples/audit_files/CDR_celldata.txt \\
  	      ./logfiles/logs_mobatch/030625-1003_allRbs/
  		
NOTE: Check that the cabling settings (located at the top of the rbsaudit file) are defined correctly for your cabinet types.
  
EOF
}

function check_file_validity()
{
	if ! test -f $1 ; then echo "File not found: $1 . Exiting..." ; exit 1 ; fi
}
function rbs_audit()
{
$gawk -v input_dir=$inputdir -v check_baseline=$check_baseline -v check_cdr=$check_cdr -v check_dump=$check_dump -v baselinefile=$baselinefile -v modumpfile=$modumpfile -v cdrfile=$cdrfile -v resultdir=${resultdir} -v input_dir_name=$input_dir_name -v baselinefilename=$baselinefilename -v exclude_from_set_commands="$exclude_from_set_commands" -v cabling_3101=$cabling_3101 -v cabling_3202=$cabling_3202 -v vobsinstallation="$vobsinstallation" '
BEGIN{
	#-rw-r--r--    1 eric     eric        30449 May 15 16:25 6000010.log
	while (sprintf("ls -l %s",input_dir) |& getline) 
	{
		gsub("\r","")
		if ($1 ~ /^-rw/)
		{
			i++
			inputfile[i]=sprintf("%s/%s",input_dir,$NF)
			inputfilename[i]=$NF
			sitename[i]=gensub(/\..*$/,"","g",$NF)
			cmdfile[i]=sprintf("%s/%s.cmd",resultdir,sitename[i])
			#printf("inputfile[%s]=%s  inputfilename[%s]=%s\n",i,inputfile[i],i,inputfilename[i])
		}
	}
	close(sprintf("ls -l %s",input_dir))
	nr_of_files=i		
	resultfile=sprintf("%s/all.res",resultdir)
	printf("Results will be saved in %s\n",resultfile)
	printf("Analysing logfiles from %s\n",input_dir) > resultfile	
	if (check_baseline == 1) printf("Using baseline file %s\n",baselinefile) >> resultfile
	if (check_cdr == 1)      printf("Using CDR file %s\n",cdrfile)  >> resultfile
	printf("========================================================================================================================\n") >> resultfile
	printf(sprintf("%-15s  %-42s   %-25s   %-15s   %-15s\n","Site","MO","Attribute","Current Value","Required Value")) >> resultfile
	printf("========================================================================================================================\n") >> resultfile
	if (check_baseline == 1) 
	{
		printf("Parsing baseline file %s ...",baselinefile)
		parse_file(baselinefile,baseline_table,baseline_motype)
		printf("Done.\n")
		#for (z in baseline_table) printf("baseline_table[%s]=%s\n",z,baseline_table[z])
	}
	for (i=1;i<=nr_of_files;i++)
	{
		print i" of "nr_of_files
		printf("Parsing input file %s ...",inputfile[i])
		parse_file(inputfile[i],site_table,site_motype,cabtype,sitename[i])
		printf("Done.\n")
		#for (z in site_table) printf("site_table[%s]=%s\n",z,site_table[z])
		printf("---------------------------------------------------%s---(%s)------------------------------------------------------------------\n",sitename[i],cabtype[sitename[i]]) >> resultfile
		if (check_baseline == 1)
		{
			printf("Comparing %s with %s ...",inputfile[i],baselinefile)
			compare(site_table,baseline_table,site_motype,baseline_motype,resultfile,sitename[i],cmdfile[i])
			printf("Done.\n")
		}
		if (check_cdr == 1)
		{
			printf("Parsing CDR file %s ...",cdrfile)
			#print cdrfile" "sitename[i]
			parse_cdr(cdrfile,sitename[i],cdr_table,cabtype)
			printf("Done.\n")
			printf("Comparing %s with %s ...",inputfile[i],cdrfile)
			compare_cdr(site_table,cdr_table,resultfile,sitename[i],cmdfile[i])
			printf("Done.\n")
		}
		delete site_table
		delete site_motype
		if (check_cdr == 1) delete cdr_table
		close(resultfile)
	}	
	#Create a sitefile containing all sites to be corrected:
	cmd_sitefile=sprintf("%s/sites_for_correction",resultdir)
	while ( sprintf("ls -l %s",resultdir) | getline)
	{
		gsub("\r","")
		if (($1 ~ /^-rw/)&&($NF ~ /.cmd$/))
		{
			print gensub(/.cmd/,"","g",$NF) >> cmd_sitefile
			k++
		}
	}
	close(sprintf("ls -l %s",resultdir))
	printf ("\nAudit result saved in %s\n",resultfile)
	if (k>0) 
	{
		printf ("%s sites need correction. To implement correction, run following commands:\n",k)
		printf ("   1- mobatch %s %s\n",cmd_sitefile,resultdir)
		printf ("   2- cvms %s <cvname> <operator>\n\n",cmd_sitefile)
	}
	else printf("No sites need correction.\n")
}
function parse_file(file,output,motype,cabtype,sitename, line,i,maxmember,array,last,var)
{
	while (getline < file)
	{
		gsub("\r","")
		if ($1 ~ /^#/ || NF<2) continue
		last=split($1,array,",")
		motype[tolower($1),tolower($2)]=gensub(/=.*$/,"","g",tolower(array[last]))
		#ATTRIBUTES
		if ($1 == "ManagedElement=1" && $2 == "productName") 
		{	
			cabtype[sitename]=$NF
			if      (cabtype[sitename] ~ /3..6/)cabling[sitename]=3   #rbs 3206/3106 
			else if (cabtype[sitename] ~ /310/) cabling[sitename]=cabling_3101
			else if (cabtype[sitename] ~ /320/) cabling[sitename]=cabling_3202
			else     { cabling[sitename] = "unknown" }
			#print "cabtype:"cabtype[sitename]
		}
		else if (tolower($2) ~ /delay|attenuation/)     #replace array by single value for feeder attenuation and delay
			output[tolower($1),tolower($2)]=$NF
		else if ((tolower($2) == "userlabel")||($3 ~/\[.*\]/))
			output[tolower($1),tolower($2)]=gensub(/^[ \t]+|[\t ]+$/,"","g",gensub($1,"","1",gensub($2,"","1",$0)))
		else if ($3 ~/Struct\{/)	#}
		{
			var=""
			maxmember=gensub(/Struct\{|\}/,"","g",$3)+0
			for (i=1 ; i<=maxmember; i++)
			{
				getline line < file ; gsub("\r","",line)
				var=sprintf("%s,%s",var,gensub(/[ \t]+|>>> [0-9]+./,"","g",line))
				output[tolower($1),tolower(sprintf("%s.%s",$2,gensub(/^.*\.| =.*$/,"","g",line)))]=gensub(/^.*= /,"","g",line)
				motype[tolower($1),tolower(sprintf("%s.%s",$2,gensub(/^.*\.| =.*$/,"","g",line)))]=gensub(/=.*$/,"","g",tolower(array[last]))				
			}
			output[tolower($1),tolower($2)]=gensub(/^,/,"","g",var)   #struct value is (not) case sensitive 
		}
		else if (tolower($3) ~ /^(true|false)$/) output[tolower($1),tolower($2)]=tolower($3)		
		else output[tolower($1),tolower($2)]=$3
	}
	close(file)
	#for (z in output) printf("file_output[%s]=%s\n",z,output[z])
	
}
function print_output(output,file)
{
	printf output
	printf output >> file
	close(file)
}
function print_silent(output,file)
{
	#printf "."
	printf output >> file
	close(file)
}

function compare(input1,input2,motype1,motype2,file,sitename,cmdfile,  array,mismatch,array1,comb,last,motype_list,z,x,var,set_lset,set_command)
{
	#input1 is the site, input2 is the reference (baseline)
	for (comb in input2)
	{
		split(comb,array,SUBSEP) #array[1] is the mo, array[2] the attribute
		if (array[1]~/=/)
		{
			if ((input1[comb] != input2[comb])&&(input1[comb]!=""))#&&(input2[comb]!=""))
			{
				mismatch[comb]=sprintf("%-15s   %-15s",input1[comb],input2[comb])
				print_silent(sprintf("%-15s  %-42s   %-25s   %s\n",sitename,array[1],array[2],mismatch[comb]),file)
			}
		}
		else
		{
			for (comb1 in motype1)
			{
				if (motype1[comb1]==array[1])				
				{
					split(comb1,array1,SUBSEP)
					if (array1[2] == array[2])
					{
						if ((input1[comb1] != input2[comb]))#rbs &&(input1[comb1]!="")&&(input2[comb]!=""))
						{
							 mismatch[comb1]=sprintf("%-15s   %-15s",input1[comb1],input2[comb])
							 print_silent(sprintf("%-15s  %-42s   %-25s   %s\n",sitename,array1[1],array1[2],mismatch[comb1]),file)
						}
					}					
				}
			}
		}
	}
	#Generate the command file
	for (comb in mismatch)
	{
		split(comb,array,SUBSEP)
		if (tolower(exclude_from_set_commands)!~ tolower(sprintf("%s,%s",gensub(/=.*$/,"","g",gensub(/^.*,/,"","g",array[1])),array[2])))
		{
			z++
			motype_list[gensub(/=.*$/,"","g",gensub(/^.*,/,"","g",array[1]))]=1
			if (array[1] ~ ",") set_lset="lset" 
			else set_lset="set"
			match(mismatch[comb],/   [^ ]+/)
			set_command[z]=sprintf("%-4s %-40s %-30s %s\n",set_lset,array[1],array[2],substr(mismatch[comb],RSTART))
		}
	}
	if (z >0)
	{
		printf("\nCommands will be saved in %s\n",cmdfile)
		printf("lt ^(") > cmdfile
		for (x in motype_list)
		{
			var=sprintf("%s%s|",var,x)
		}		
		printf("%s)$\n",gensub(/\|$/,"","g",var)) >> cmdfile
		for (z in set_command) printf set_command[z] >> cmdfile
	}
}
function parse_cdr(file,sitename,output,cabtype,  column,site,sector,array,cell,attribute,i)
{
	#takes the cdr file and output the tables "output" and "cell_list"
	while (getline < file)
	{
		gsub("\r","")
		if (NF ==2 && $1 ~ /^[0-9]+$/)	
		{
			if (column[$1] == "") 
			{
				 column[$1]=tolower($2) #; print $1"   "column[$1]
				 if (tolower($2) == "site") site=$1 
				 if (tolower($2) == "sector") sector=$1
			}
		}
		else
		{
			if ($site == sitename)
			{
				for (i=1;i<=NF;i++)
				{
					split(column[i],array,",") 
					attribute=array[2]
					if (array[1] == "sector")
					{
						output[sprintf("sector=%s",$sector),attribute]=$i
						#printf("output[%s,%s]=%s\n",sprintf("sector=%s",$sector),attribute,$i)
					}
					else if (array[1]  ~ /^(antennabranch)$/) 
					{
						output[sprintf("sector=%s,%s=a",$sector,array[1]),attribute]=$i
						output[sprintf("sector=%s,%s=b",$sector,array[1]),attribute]=$i
					}
					else if (array[1] ~ /^(antfeedercable|antjumpercable)$/)
					{
						if (cabling[sitename] == 3)
						{
							#AntFeederCable=1A,1B,2A,2B,3A,3C
							output[sprintf("%s=%sa",array[1],$sector),attribute]=$i
							output[sprintf("%s=%sb",array[1],$sector),attribute]=$i
						}
						else if (cabling[sitename] == 1)
						{
							#sect1=1,2 ; sect2=3,4 ; sect3=5,6
							output[sprintf("%s=%s",array[1],1+2*($sector-1)),attribute]=$i
							output[sprintf("%s=%s",array[1],2+2*($sector-1)),attribute]=$i
						}
						else if (cabling[sitename] == 2)
						{
							#sect1=1,4 ; sect2=2,5 ; sect3=3,6
							output[sprintf("%s=%s",array[1],$sector),attribute]=$i
							output[sprintf("%s=%s",array[1],$sector+3),attribute]=$i
						}
						else if (cabling[sitename] == "unknown") print "Cabling configuration for "sitename"is unknown !!!!"		
					}	
				}
			}
		}
	}
	close(file)
	#for (z in output) { printf("cdr_output[%s]=%s\n",z,output[z]) }
}					

function compare_cdr(output1,output2,file,sitename,cmdfile,   comb,array,mismatch,z,x,set_lset,set_command,var,motype_list,value)
{
	#cdr table is output2
	for (comb in output1) 
	{
		split(comb,array,SUBSEP)
		#print "output1",array[1],array[2],output1[comb]
	}
	for (comb in output2)
	{
		split(comb,array,SUBSEP) #array[1] is the mo, array[2] the attribute
		#print "output2",array[1],array[2],output2[comb]
		if ((output1[comb] != output2[comb])&&(output1[comb]!="")&&(output2[comb]!=""))
		{
			mismatch[comb]=sprintf("%-15s    %-15s",output1[comb],output2[comb])
			print_silent(sprintf("%-15s  %-42s   %-25s   %s\n",sitename,array[1],array[2],mismatch[comb]),file)
		}
	}
	for (comb in mismatch)
	{
		split(comb,array,SUBSEP)
		if (tolower(exclude_from_set_commands)!~ tolower(sprintf("%s,%s",gensub(/=.*$/,"","g",gensub(/^.*,/,"","g",array[1])),array[2])))
		{
			z++
			motype_list[gensub(/=.*$/,"","g",gensub(/^.*,/,"","g",array[1]))]=1
			if (array[1] ~ ",") set_lset="lset" 
			else set_lset="set"
			match(mismatch[comb],/   [^ ]+/)
			value=substr(mismatch[comb],RSTART)
			value=gensub(/^ *| *$/,"","g",value)
			if (array[2] ~ /delay|attenuation/) value=sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",value,value,value,value,value,value,value,value,value,value,value,value)
			set_command[z]=sprintf("%-4s %-40s %-30s %s\n",set_lset,array[1],array[2],value)
		}
	}
	if (z >0)
	{
		printf("\nCommands will be saved in %s\n",cmdfile)
		printf("lt ^(") >> cmdfile
		for (x in motype_list)
		{
			var=sprintf("%s%s|",var,x)
		}		
		printf("%s)$\n",gensub(/\|$/,"","g",var)) >> cmdfile
		for (z in set_command) printf set_command[z] >> cmdfile
	}

}

function print_output1(output)
{
	for (comb in output)
	{
		split(comb,array,SUBSEP)
		#if ((tolower(array[1]) ~ /^sid/) || (tolower(array[2]) == "rctfi"))
		#{
			printf("%s   %s           %s\n",tolower(array[1]),tolower(array[2]),output[tolower(array[1]),tolower(array[2])])
			#printf("%s   %s           %s\n",tolower(array[1]),tolower(array[2]),motype[tolower(array[1]),tolower(array[2])])
		#}
	}	
}
'
}

echo -e "\033[1;31m\n!!!! WARNING: Option -b is obsolete, use the moshell command \"diff\" instead !!!! \n\033[0m"

check_cdr=0
check_baseline=0
while getopts "c:b:" options
do
case $options in
c) cdrfile=$OPTARG
   check_cdr=1
   check_file_validity $cdrfile
  ;;   
b) baselinefile=$OPTARG
   check_baseline=1
   check_file_validity $baselinefile
   baselinefilename=$(basename $baselinefile)
  ;;    
*) print_usage ; exit 1
  ;;
esac
done 
shift $(($OPTIND - 1))
if test $OPTIND -eq 1 ; then print_usage ; exit 1; fi

case $# in
1)  if test -d "$1" ; then inputdir="$1" ; inputbase=$(basename $inputdir) ; input_dir_name=$(basename $inputdir)
    else echo "Input Directory $1 not found. Exiting...." ; exit 1
    fi
    ;;    
*) print_usage ; exit 1
  ;;   
esac

date_time=$(date +%y%m%d-%H%M)
resultdir=${logdir}/${date_time}_${inputbase}
if ! mkdir -p $resultdir ; then "Failed to create result directory: $resultdir . Exiting ..." ; exit 1 ; fi 

rbs_audit
		
