#!/bin/bash
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html

#-------------------------------------------------------------------------------
#=head1  syslog 
#=head2  syslog command that setsup the syslogd for MS, SV and nodes.
#        On MS, it makes sure all the xCAT messages goes to /var/log/messages file,
#               it enables syslogd receving logs from remote machies. 
#        On MS, it sends all the messages to MS,
#               it enables syslogd receving logs from remote nodes. 
#        On node,  it sends all the messages its master.  
#        Input: none, it takes the following environment variables: 
#           OSVER: possible values are sles10, fedora8, redhat5, aix etc.   
#=cut
#-------------------------------------------------------------------------------
if [ "$SYSLOG" = "ignore" ]; then
    echo "The value of syslog is '$SYSLOG'."
    exit 0
elif [ -n "$SYSLOG" ]; then
    echo "Warning: The value of syslog '$SYSLOG' is not supported, but will still run syslog script."
fi

if [ "$(uname -s|tr 'A-Z' 'a-z')" = "linux" ];then
   str_dir_name=`dirname $0`
   . $str_dir_name/xcatlib.sh
fi

master=$MASTER
conf_file="/etc/syslog.conf"
sysconfig="/etc/sysconfig/syslog"
init="/etc/init.d/syslog"
ng=0
isSN=0
isLinux=1
isRsyslog=0
isC3=0
xCATSettingsSTART="xCAT settings START"
xCATSettingsEND="xCAT settings END"
xCATSettingsOLD="xCAT settings"
xCATSettingsInfo="Entries between the START and END lines will be replaced on the next xCAT install or update"
#systemdEnabled=0
# pmatch determines if 1st argument string is matched by 2nd argument pattern

pmatch ()
{
  case $1 in
    $2) return 0;;  # zero return code means string matched by pattern
  esac

  return 1          # non-zero return code means string not matched by pattern
}

# is_lsb_ubuntu exit status indicates whether system appears to be Ubuntu.
# Using required /etc/lsb-release file, instead of optional lsb_release command.

is_lsb_ubuntu ()
{
    awk '
        (match($0, "^[ \t]*DISTRIB_ID=") == 1) {    # A DISTRIB_ID line
            id = substr($0, RLENGTH + 1)            # Save its value
        }

        END {
            # Examine last DISTRIB_ID value to see if Ubuntu indicated

            if (match(id, "^(Ubuntu|\"Ubuntu\")[ \t]*$") == 1) {
                exit 0    # Ubuntu
            }
            exit 1        # Not Ubuntu
        }

    ' /etc/lsb-release >/dev/null 2>&1

    # Routine exit status is exit status of the last command -- the awk script.
    #
    #   Note: if /etc/lsb-release does not exist, the exit status indicates
    #         failure (not Ubuntu), which is the correct outcome.
}

config_Rsyslog_C3()
{
  isReceiving=0
  isLocal=$1

  if [ -f /etc/xCATMN ] ||  [ $isSN -eq 1 ] 
  then 
    isReceiving=1
  fi

  if [ ! -f $2.XCATORIG ]; then
    cp -f $2 $2.XCATORIG
  fi

  grep "$xCATSettingsOLD$" $conf_file 2>&1 1> /dev/null
  if [ $? -eq 0 ]; then
       #remove the older version syslog rule generated by xCAT
       sed -i "/$xCATSettingsOLD$/,+1 d" $2
  fi

  grep "$xCATSettingsSTART" $conf_file 2>&1 1> /dev/null
  if [ $? -eq 0 ]; then
       #remove the previous syslog rule generated by xCAT
       sed -i "/$xCATSettingsSTART/,/$xCATSettingsEND/ d" $2
  fi

  # Mark the start of xCAT section
  echo "# $xCATSettingsSTART" >> $2
  echo "# $xCATSettingsInfo" >> $2
  #enable to receive remote logging
  if [ $isReceiving -eq 1 ]; then
      #listen on the udp and tcp port to receive the remote logs
      sed -i 's/^\#\(\s\)*\$ModLoad\(\s\)*imudp/\$ModLoad imudp/ 
                     s/^\#\(\s\)*\$UDPServerRun/\$UDPServerRun/; 
                     s/#\$ModLoad imtcp/\$ModLoad imtcp/; 
                     s/#\$InputTCPServerRun 514/\$InputTCPServerRun 514/' $2
  fi

  #enable to send the logging to master
  if [ $isLocal -eq 1 ]; then
      #enable the MN to log all the logs from CN and MN itself
      sed -i 's/\(^[^\#].*\/var\/log\/messages\)/\#\1/g' $2
      echo "#*.debug  /var/log/messages" >> $2
      touch  /var/log/messages  
      if ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
        chown syslog:adm /var/log/messages
        sed -i 's/\$PrivDropToGroup syslog/\$PrivDropToGroup adm/' $2
        chown syslog:adm /var/log/xcat
      fi
  else
      sed -i 's/^\(\*\..*\)/\#\1/; 
                     s/^\(news\|local7\|mail\|authpriv\|cron\|kern\)\./\#\1\./' $2
      echo "*.* @$master" >> $2
  fi 
  # Mark the end of xCAT section
  echo "# $xCATSettingsEND" >> $2
}

# This sets up rsyslog 8.x, different from the previous rsyslog versions.  
# Instead of updating /etc/rsyslog.conf  for forwarding to a remote host,
# You update /etc/rsyslog.d/remote.conf.  The /etc/sysconfig/rsyslog file does not exist.
# This is only for Linux, since AIX does not use rsyslog.  It ships its own syslog in an lpp,
# at least at the time of this code being written

config_rsyslog_V8()
{
  
  goLocal=0;
  conf_file="/etc/rsyslog.conf"
  remoteconf="/etc/rsyslog.d/remote.conf"

  #for Cumulus OS inside ONIE switches
  if [ -f /etc/os-release ]; then
     cat /etc/os-release |grep -i -e "^NAME=[ \"']*Cumulus Linux[ \"']*$" >/dev/null 2>&1 && remoteconf="/etc/rsyslog.d/99-syslog.conf"
  fi

  # If this is a Management Node or Service Node, then it will be receiving syslog entries from the
  # compute nodes. Management Node is receiving from Service Nodes and possibly compute nodes.
  # They will all be put in /var/log/messages
  # For the service node, if site table svloglocal  is set then we will keep the logs on the servicenode
  # and not forward to the Management Node. 

  #now handling where the logs go, if goLocal=1 then log local, if not forward to MN
  if [ -f /etc/xCATMN ]; then
     goLocal=1
  else
    # check to see if service node should forward of keep logs
    if [ $isSN -eq 1 ]; then
       if [ -n "$SVLOGLOCAL" ] && [ $SVLOGLOCAL -eq 1 ]; then
         goLocal=1  
       fi
    fi
  fi

  # backup rsyslog.conf
  if [ ! -f $conf_file.XCATORIG ]; then
    cp -f $conf_file $conf_file.XCATORIG
  fi

  # check if already an old entry by xCAT. If so, we need to remove it
  grep "$xCATSettingsOLD$" $conf_file 2>&1 1> /dev/null
  if [ $? -eq 0 ]; then
       sed -i "/$xCATSettingsOLD/,+1 d" $conf_file
  fi

  grep "$xCATSettingsOLD$" $remoteconf 2>&1 1> /dev/null
  if [ $? -eq 0 ]; then
       sed -i "/$xCATSettingsOLD/,+1 d" $remoteconf
  fi

  # check if already a previous entry by xCAT. If so, we need to remove it
  grep "$xCATSettingsSTART" $conf_file 2>&1 1> /dev/null
  if [ $? -eq 0 ]; then
        sed -i "/$xCATSettingsSTART/,/$xCATSettingsEND/ d" $conf_file
  fi

  grep "$xCATSettingsSTART" $remoteconf 2>&1 1> /dev/null
  if [ $? -eq 0 ]; then
     sed -i "/$xCATSettingsSTART/,/$xCATSettingsEND/ d" $remoteconf
  fi

  if [ $goLocal -eq 1 ]; then
    #logging is local, do not forward
    #making sure all the messages goes to /var/log/messages
    touch  /var/log/messages
    if ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
      chown syslog:adm /var/log/messages
      sed -i 's/\$PrivDropToGroup syslog/\$PrivDropToGroup adm/' $conf_file
      chown syslog:adm /var/log/xcat
    fi

    #comment out the rules which will write logs to /var/log/messages
    # to prevent duplicate logs after "syslog" script is run 
    sed -i '/^[^#].*\/var\/log\/messages/s/^/#/' $conf_file

    # Mark the start of xCAT section
    echo "# $xCATSettingsSTART" >> $conf_file
    echo "# $xCATSettingsInfo" >> $conf_file
    echo "#*.debug   /var/log/messages"  >> $conf_file
    # Need to uncomment the lines $ModLoad imudp.so and $UDPServerRun 514,
    # to make the MN be able to receive syslog from remote hosts
    if [ -f "$remoteconf" ]; then
        ##listen on tcp and udp port to enable receiving the xcat debug logs 
        ##forwarded  via tcp/udp protocol
        sed -i 's/#\$ModLoad imudp.so/\$ModLoad imudp.so/; 
                       s/#\$UDPServerRun 514/\$UDPServerRun 514/; 
                       s/#\$ModLoad imtcp.so/\$ModLoad imtcp.so/; 
                       s/#\$InputTCPServerRun <port>/\$InputTCPServerRun 514/' $remoteconf
    fi


    ##listen on tcp and udp port to enable receiving the xcat debug logs 
    ##forwarded  via tcp/udp protocol
    if [ -f "$conf_file" ]; then
        #rhels7.4 ships rsyslogd 8.24.0, which does not ship remote.conf
        #the relevant sections are included in rsyslog.conf
        sed -i '/#\$ModLoad \+imudp\|imtcp\|imudp.so\|imtcp.so/s/^#//;
                       /#\$InputTCPServerRun\|UDPServerRun.*/s/^#//' $conf_file

        #ubuntu16.04 ships rsyslog 8.16.0,which does not ship remote.conf
        #the configuration for UDP and TCP syslog reception is in rsyslog.conf
        sed -i 's/#module(load="imudp")/module(load="imudp")/;
                s/#input(type="imudp" port="514")/input(type="imudp" port="514")/;
                s/#module(load="imtcp")/module(load="imtcp")/;
                s/#input(type="imtcp" port="514")/input(type="imtcp" port="514")/' $conf_file
    fi
    
    if [ $isSN -eq 1 ] ; then
        [ -d "/etc/xcat/rsyslog.conf" ] && cp -a /etc/xcat/rsyslog.conf/* /etc/rsyslog.d/
        if [ -d "/etc/xcat/logrotate.conf" ];then 
            mkdir -p "/etc/logrotate.d/"
            cp -a /etc/xcat/logrotate.conf/* /etc/logrotate.d/
        fi
    fi

    # Mark the end of xCAT section
    echo "# $xCATSettingsEND" >> $conf_file
  else
    # not logging local, forward logging
    # backup the existing remote.conf file from the install
    if [ -f $remoteconf ] && [ ! -f $remoteconf.XCATORIG ]; then
        cp -f $remoteconf $remoteconf.XCATORIG
    fi

    if [ $isSN -eq 1 ];then
        ##listen on tcp and udp port to enable receiving the xcat debug logs 
        ##forwarded  via tcp/udp protocol
        [ -f "$remoteconf" ] && sed -i '/#\$ModLoad \+imudp\|imtcp\|imudp.so\|imtcp.so/s/^#//;
                       /#\$InputTCPServerRun\|UDPServerRun.*/s/^#//' $remoteconf 

        [ -f "$conf_file" ] && sed -i '/#\$ModLoad \+imudp\|imtcp\|imudp.so\|imtcp.so/s/^#//;
                       /#\$InputTCPServerRun\|UDPServerRun.*/s/^#//' $conf_file

        [ -f "/etc/rsyslog.d/xcat-cluster.conf" ] && rm -f "/etc/rsyslog.d/xcat-cluster.conf" ;
        [ -f "/etc/rsyslog.d/xcat-compute.conf" ] && rm -f "/etc/rsyslog.d/xcat-compute.conf" ;
        [ -f "/etc/rsyslog.d/xcat-debug.conf" ] && rm -f "/etc/rsyslog.d/xcat-debug.conf" ;

        [ -f "/etc/logrotate.d/xcat" ] && rm -f "/etc/logrotate.d/xcat"
        
    fi


    # add xCAT entries
    echo "# $xCATSettingsSTART" >> $remoteconf
    echo "# $xCATSettingsInfo" >> $remoteconf
    echo "*.* @$master" >> $remoteconf
    echo "# $xCATSettingsEND" >> $remoteconf
 fi
 # restart syslog ( could be service or systemctl call depending on the OS)
 restartservice syslog

}


#echo "NTYPE=$NTYPE,OSVER=$OSVER,OSTYPE=$OSTYPE"

if [ "$NTYPE" = service ]; then 
  isSN=1
fi

#if [ -e /etc/systemd ]; then
#  systemdEnabled=1
#fi

# check if this is rsyslog version 8,  setup is different no matter what OS.
# We only update the /etc/rsyslog.d/remote.conf file to point to the xcatmaster.
# Do not even touch rsyslog.conf
# There is no /etc/sysconfig/rsyslog file, so we use  rsyslogd -v to get the version
if [ -e "/sbin/rsyslogd" -o -e "/usr/sbin/rsyslogd" ]; then
    SYSLOGPROD=`rsyslogd -v | grep rsyslogd |awk {'print $1'}`
    SYSLOGVER=`rsyslogd -v | grep rsyslogd |awk {'print $2'}`
    if ( pmatch $SYSLOGPROD "*rsyslogd*" ) && ( pmatch $SYSLOGVER "8*" ); then
      config_rsyslog_V8 
      #keep a record
      logger -t xcat -p local4.info "Install: rsyslog version 8 setup"
      exit 0
    fi
fi

if [ "$(uname -s)" = "Linux" ]; then
  if ( pmatch $OSVER "fedora*" ) || ( pmatch $OSVER "rhels5*" ) || ( pmatch $OSVER "rhel6*" ) || ( pmatch $OSVER "rhels6*" ) || [ -f /etc/fedora-release ] || [ -f /etc/redhat-release ] || ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
    if [ -e /etc/rsyslog.conf ]; then
      conf_file="/etc/rsyslog.conf"
      sysconfig="/etc/sysconfig/rsyslog"
      #init="/etc/init.d/rsyslog"
      #if [ $systemdEnabled -eq 1 ]; then
      #   init="rsyslog"
      #fi
      isRsyslog=1
      if ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
        sysconfig="/etc/default/rsyslog"
      fi
    fi
  else 
    if ( pmatch $OSVER "sles*" ) || ( pmatch $OSVER "suse*" ) || [ -f /etc/SuSE-release ]; then
      #find out which syslog is used for SLES, syslog or syslog-ng
      result=`grep "^SYSLOG_DAEMON=" $sysconfig 2>&1`
      if ( pmatch $result "*syslog-ng*" ); then
        conf_file="/etc/syslog-ng/syslog-ng.conf"
        ng=1
      fi
    fi
  fi 
else
  sysconfig=  #AIX does not have this file
  isLinux=0;
fi

#echo "isSN=$isSN, isLinux=$isLinux, ng=$ng"
#echo "sysconfig=$sysconfig, confgile=$conf_file"



#handle sysconfig file to make remote logging possible 
if [ $isLinux -eq 1 ] && [ -e $sysconfig ]; then 
  if [ ! -f "$sysconfig.XCATORIG" ]; then
    cp -f $sysconfig $sysconfig.XCATORIG
  fi

  #check if it is ryslog version 3, it has totally different settings in /etc/syslog.conf
  if [ $isRsyslog -eq 1 ]; then
    grep "SYSLOGD_OPTIONS" $sysconfig | grep -e "[\-c 3|\-c3|\-c4|\-c 4]" 2>&1 1> /dev/null
    if [ $? -eq 0 ]; then
      isC3=1
    fi
  fi
  
  #no need to change anything for rsyslog version 3 for /etc/sysconf/rsyslog
  if [ $isC3 -eq 0 ]; then 
    if [ -f /etc/xCATMN ]; then
      #on MN: make the syslogd be able to receive remote logs 
      awk  '{if ($0 ~ /^SYSLOGD_OPTIONS=|^SYSLOGD_PARAMS=/) { 
            if ($0 !~ /-r/) {sub(/-/, "-r -", $0)}
            if (($0 !~ /-m0/) && ($0 !~/-m 0/)) { sub(/-/, "-m 0 -", $0)}
            print $0}
          else { print $0}}'  $sysconfig > $sysconfig.tmp 
    else
      if [ $isSN -eq 1 ]; then
        #on SN: make the syslog be able to receive and forward remote logs
        awk '{if($0 ~ /^SYSLOGD_OPTIONS=|^SYSLOGD_PARAMS=/) {
              if ($0 !~ /-r/) {sub(/-/, "-r -", $0)}
              if ($0 !~ /-h/) {sub(/-/, "-h -", $0)}
              if (($0 !~ /-m0/) && ($0 !~/-m 0/)) { sub(/-/, "-m 0 -", $0)}
              print $0}
            else { print $0}}'  $sysconfig > $sysconfig.tmp 
      else
        ##turn off the time marker on all 
        awk '{if($0 ~ /^SYSLOGD_OPTIONS=|^SYSLOGD_PARAMS=/) {
              if (($0 !~ /-m0/) && ($0 !~/-m 0/)) { sub(/-/, "-m 0 -", $0)}
              print $0}
            else {print $0}}' $sysconfig > $sysconfig.tmp 
      fi
    fi
    mv -f $sysconfig.tmp $sysconfig   
  fi
fi  


#syslog-ng has different way of enabling log forwarding
if [ $ng -eq 1 ]; then
  if [ $isSN -eq 1 -o -f /etc/xCATMN ]; then
    if [ ! -f $conf_file.XCATORIG ];  then
       cp -f $conf_file $conf_file.XCATORIG
    fi
    sed -i 's/#udp(ip("0.0.0.0/udp(ip("0.0.0.0/' $conf_file
  fi
fi



#now handling where the logs go
goLocal=0;
if [ -f /etc/xCATMN ]; then
  goLocal=1
else 
  if [ $isSN -eq 1 ]; then
     if [ -n "$SVLOGLOCAL" ] && [ $SVLOGLOCAL -eq 1 ]; then
       goLocal=1  
     fi
  fi
fi

if [ $isC3 -eq 1 ]; then 
  config_Rsyslog_C3 $goLocal $conf_file
else
  if [ $goLocal -eq 1 ]; then
    #making sure all the messages goes to /var/log/messages
    touch  /var/log/messages 
    if ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
      chown --reference=/var/log /var/log/messages
      chown --reference=/var/log /var/log/xcat
    fi
    if [ $ng -eq 0 ]; then
      if [ ! -f $conf_file.XCATORIG ]; then
        cp -f $conf_file $conf_file.XCATORIG
      fi

      grep "xCAT settings" $conf_file 2>&1 1> /dev/null
      if [ $? -eq 0 ]; then
          sed -i "/# xCAT settings/,$ d" $conf_file
      fi

      if [ $isLinux -eq 0 ]; then # aix
          echo "# xCAT settings" >> $conf_file
          echo "*.debug   /var/log/messages  rotate 1024K files 5" >> $conf_file
      fi
    else
       #enable the settings that will log to local files in syslog-ng
       sed -i '/destination messages/s/^#*//; 
                      /destination(messages)/s/^#*//; 
                      /destination warn/s/^#*//; 
                      /destination(warn)/s/^#*//'  $conf_file
    fi
    
    #Ubuntu doesn't have sysconfig 
    # so configuring the MN to receive UDP connections here.
    if ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
      egrep \('^\$UDPServerRun 514'\|'^\$ModLoad imudp'\) $conf_file > /dev/null 2>&1;
      if [ $? -eq 1 ]; then
        echo "\$ModLoad imudp" >> $conf_file;
        echo "\$UDPServerRun 514" >> $conf_file;
      fi
    fi 
  else 
    #now make the syslogd fowarding the messages to the the master
    if [ $ng -eq 1 ]; then
      if [ ! -f $conf_file.XCATORIG ]; then
        cp -f $conf_file $conf_file.XCATORIG
      fi
      grep "xCAT settings" $conf_file 2>&1 1> /dev/null
      if [ $? -eq 0 ]; then
          sed -i "/# xCAT settings/,$ d" $conf_file
      fi
      echo "# xCAT settings" >> $conf_file
      echo "destination loghost { udp(\"$master\"); };" >> $conf_file
      echo 'log { source(src); destination(loghost); };' >> $conf_file
 
      # remove the settings that will log to local files
      sed -i '/destination messages/s/^/#/; 
                     /destination(messages)/s/^/#/; 
                     /destination warn/s/^/#/; 
                     /destination(warn)/s/^/#/;' $conf_file
    else 
      if [ -f $conf_file.XCATORIG ]; then 
        rm -f $conf_file 
      else 
        mv -f $conf_file $conf_file.XCATORIG
      fi
      echo "# xCAT settings" > $conf_file
      if [ $isLinux -eq 0 ]; then
        echo "*.debug @$master" >> $conf_file
      else
        if ( pmatch $OSVER "ubuntu*" ) || ( is_lsb_ubuntu ) || ( pmatch $OSVER "debian*" ); then
          echo "\$ModLoad imuxsock" >> $conf_file
          echo "*.* @$master" >> $conf_file
        else
          echo "*.* @$master" >> $conf_file
        fi 
      fi
    fi
  fi
fi

#restart the syslog daemon to take the new conf file settings
if [ $isLinux -eq 0 ]; then
  PARSE_SRC_STATE="-e1d;s/.* \([a-zA-Z0-9]*\)$/\1/"
  state=$(LC_ALL=C lssrc -s syslogd | LC_ALL=C sed "$PARSE_SRC_STATE")
  if [ -n "$state" ] && [ "$state" = "active" ]; then
     stopsrc -s syslogd
  fi
     
  #wait for syslogd to fully started
  RETRY_LIMIT=30          # number of 2 second retry intervals (60 second total)
  i=$RETRY_LIMIT
  while :
  do
      ret=`LC_ALL=C startsrc -s syslogd 2>&1`
      if ( pmatch $ret "*PID*" ); then
        break
      fi

      i=$((i - 1))
      if [ $i -gt 0 ]; then
          sleep 2
      else
          break
      fi
  done
else
  #if [ $systemdEnabled -eq 1 ]; then 
  #  systemctl restart $init.service 
  #else
  #  $init restart
  #fi
  restartservice syslog
fi

#keep a record
logger -t xcat -p local4.info "Install: syslog setup"
exit 0
