#!/bin/bash

# Version 0.2 .

# This script serves merely as an example. It was deliberately kept as simple as possible and probably should be improved. 

# use the '-s' option to skip the initial folder and group checking and creation. Never use this option for the first run.
# use the '-o' option to only perform the initial folder and group checking and creation.

# Base location of the YUP tree.
YUP2ZLM_YUP_TREE="/var/yup"
# How we must name the patch bundle groups
YUP2ZLM_PATCH_BUNDLE_BASE_NAME="Patches"
YUP2ZLM_SEC_PATCH_BUNDLE_EXT="Security"
YUP2ZLM_REC_PATCH_BUNDLE_EXT="Recommended"
YUP2ZLM_OPT_PATCH_BUNDLE_EXT="Optional"
YUP2ZLM_KER_SEC_PATCH_BUNDLE_EXT="Security-kernel"
YUP2ZLM_KER_NONSEC_PATCH_BUNDLE_EXT="Nonsecurity-kernel"
# Only supported products are SLES10 and/or SLED10 - this is YUP syntax.
YUP2ZLM_PRODUCTS="SLES10,SLED10"
# List of the architectures we are interested in for the products.
YUP2ZLM_ARCHS="i586"
# ZLM 7.2 folder where all SLES 10 related patches and patch groups should reside in.
YUP2ZLM_SLES10_PATCHES_FOLDER="/Patches/Servers"
# ZLM 7.2 folder where all SLED 10 related patches and patch groups should reside in.
YUP2ZLM_SLED10_PATCHES_FOLDER="/Patches/Desktops"
# Credentials to connect to ZLM 7.2 - you might want to give this file permissions 700.
YUP2ZLM_ZLMAN_CMD="/usr/bin/zlman -U administrator -P novell"
# Names of the server kinds for which we want to create test and production patch bundle groups
YUP2ZLM_SERVER_GROUPS="web,app,dbs"
# Names of the desktop kinds for which we want to create test and production patch bundle groups
YUP2ZLM_DESKTOP_GROUPS=""
# Environments in which you want patches to get loaded - comma or space separated.
YUP2ZLM_ENV_LOAD="test"
# Environments in which patches should not yet be loaded - comma or space separated.
YUP2ZLM_ENV_NOTLOAD="prod"
# What the transaction folder should be called
YUP2ZLM_TRANS_FOLDER="Committed"

if [ "$YUP2ZLM_SLES10_PATCHES_FOLDER" = "$YUP2ZLM_SLED10_PATCHES_FOLDER" ] ; then
 echo Server related patches folder and desktop related patches folder must differ.
 exit 1
fi

ENV_LOAD=`echo $YUP2ZLM_ENV_LOAD | tr ',' ' '`
ENV_NOTLOAD=`echo $YUP2ZLM_ENV_NOTLOAD | tr ',' ' '`
ENVIRONMENTS="$ENV_LOAD"" ""$ENV_NOTLOAD"

if [ "$1" = "-s" ] ; then
  :
else
  FORMEDPATH="/"
  for PATHELEMENT in `echo $YUP2ZLM_SLES10_PATCHES_FOLDER | tr '/' ' '` ; do
    $YUP2ZLM_ZLMAN_CMD bfc "$PATHELEMENT" "$FORMEDPATH" 
    FORMEDPATH="${FORMEDPATH}/$PATHELEMENT"
  done    
  FORMEDPATH="/"
  for PATHELEMENT in `echo $YUP2ZLM_SLED10_PATCHES_FOLDER | tr '/' ' '` ; do
    $YUP2ZLM_ZLMAN_CMD bfc "$PATHELEMENT" "$FORMEDPATH" 
    FORMEDPATH="${FORMEDPATH}/$PATHELEMENT"
  done    
fi
# ----------------------------------------------------------------------------------------------------------------------
# ------------------------------- For every product in the YUP tree ... ------------------------------------------------
# ----------------------------------------------------------------------------------------------------------------------
for PRODUCT_FOLDER in `ls ${YUP2ZLM_YUP_TREE}` ; do
  CURRENT_PAT_BUNDLE=""
  if echo "$YUP2ZLM_PRODUCTS" | grep "$PRODUCT_FOLDER" - 1>/dev/null 2>&1 ; then
    if [ "$PRODUCT_FOLDER" = "SLES10" ] ; then
      PRODUCT="sles-10"
      CURRENTFOLDER="$YUP2ZLM_SLES10_PATCHES_FOLDER"
      DEVICE_GROUPS="$YUP2ZLM_SERVER_GROUPS"
    elif [ "$PRODUCT_FOLDER" = "SLED10" ] ; then
      PRODUCT="sled-10"
      CURRENTFOLDER="$YUP2ZLM_SLED10_PATCHES_FOLDER"
      DEVICE_GROUPS="$YUP2ZLM_DESKTOP_GROUPS"
    fi
# ----------------------------------------------------------------------------------------------------------------------
# ------------------------------- For every architecture for that product in the YUP tree ... --------------------------
# ----------------------------------------------------------------------------------------------------------------------
    for ARCH in `ls ${YUP2ZLM_YUP_TREE}/${PRODUCT_FOLDER}`; do
      if echo "$YUP2ZLM_ARCHS" | grep "$ARCH" - 1>/dev/null 2>&1 ; then
        PRODARCH="${PRODUCT}-${ARCH}"
        cd ${YUP2ZLM_YUP_TREE}/${PRODUCT_FOLDER}/${ARCH}/repodata
        THIS_ARCH_OK="true"
	if [ "$1" = "-s" ] ; then
  	  :
	else
	  $YUP2ZLM_ZLMAN_CMD bfc "$PRODUCT" "$CURRENTFOLDER"
	  $YUP2ZLM_ZLMAN_CMD bfc "$ARCH" "$CURRENTFOLDER"/"$PRODUCT" 
          $YUP2ZLM_ZLMAN_CMD bfc  "$YUP2ZLM_TRANS_FOLDER" "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"
          DEVICE_KIND=""
          for DEVICE_KIND in `echo $DEVICE_GROUPS | tr ',' ' '` ; do
	    if [ -n "$DEVICE_KIND" ] ; then 
	      $YUP2ZLM_ZLMAN_CMD bfc "$DEVICE_KIND" "$CURRENTFOLDER"
	      $YUP2ZLM_ZLMAN_CMD bfc "$PRODUCT" "$CURRENTFOLDER"/"$DEVICE_KIND"
	      $YUP2ZLM_ZLMAN_CMD bfc  "$ARCH" "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"
	      for ENVIRONMENT in $ENVIRONMENTS ; do
		if [ -n "$ENVIRONMENT" ] ; then
	          $YUP2ZLM_ZLMAN_CMD bfc "$ENVIRONMENT" "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"/"$ARCH"
		fi
	      done
            fi
	  done
  	  BUNDLE="" 
          for BUNDLE in "$YUP2ZLM_SEC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_REC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_OPT_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_KER_SEC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_KER_NONSEC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" ; do
  	    if $YUP2ZLM_ZLMAN_CMD bgm "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$BUNDLE" 1>/dev/null 2>&1; then
              :	
  	    else
  	      if $YUP2ZLM_ZLMAN_CMD bgc "$BUNDLE" "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH" ; then
                :  	
  	      else
  	        echo "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$BUNDLE" could not be created - check folder path.
  	        THIS_ARCH_OK="false" 
	        break
  	      fi
  	    fi
  	  done
          if [ "$THIS_ARCH_OK" = "false" ] ; then
            echo Errors found - skipping architecture "$ARCH" for product "$PRODUCT".
            continue 
          fi
	    for ENVIRONMENT in $ENVIRONMENTS ; do
	      if [ -n "$ENVIRONMENT" ] ; then
              for DEVICE_KIND in `echo $DEVICE_GROUPS | tr ',' ' '` ; do
	        if [ -n "$DEVICE_KIND" ] ; then
                  BUNDLE=""
                  for BUNDLE in "$YUP2ZLM_SEC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_REC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_OPT_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_KER_SEC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" \
				  "$YUP2ZLM_KER_NONSEC_PATCH_BUNDLE_EXT"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" ; do
                    if $YUP2ZLM_ZLMAN_CMD bgm "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"/"$ARCH"/"$ENVIRONMENT"/"$DEVICE_KIND"_"$ENVIRONMENT"_"$BUNDLE" 1>/dev/null 2>&1; then
                      :
                    else
                      if $YUP2ZLM_ZLMAN_CMD bgc "$DEVICE_KIND"_"$ENVIRONMENT"_"$BUNDLE" "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"/"$ARCH"/"$ENVIRONMENT" ; then
                        :
                      else
                        echo "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"/"$ARCH"/"$ENVIRONMENT"/"$DEVICE_KIND"_"$ENVIRONMENT"_"$BUNDLE" could not be created - check folder path.
                        THIS_ARCH_OK="false"
                        break
                      fi
                    fi
                  done
                  if [ "$THIS_ARCH_OK" = "false" ] ; then
	            break  
                  fi
	        fi
              done
	    fi
            if [ "$THIS_ARCH_OK" = "false" ] ; then
	      break  
            fi
       	  done
        fi
        if [ "$THIS_ARCH_OK" = "false" ] ; then
          echo Errors found - skipping architecture "$ARCH" for product "$PRODUCT".
          continue 
        fi
	if [ "$1" = "-o" ] ; then
	  :
	else  
	  EXISTING_PATCHES=`$YUP2ZLM_ZLMAN_CMD bl "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$YUP2ZLM_TRANS_FOLDER" | grep '.*-[0-9][0-9][0-9][0-9][ 0-9].*' | grep 'Software Bundle' | cut -d '|' -f 1 | tr -d ' ' | sort -n`
# ----------------------------------------------------------------------------------------------------------------------
# ------------------------------- End of preliminary work - we start adding patches now --------------------------------
# ----------------------------------------------------------------------------------------------------------------------
          for PATCHFILE in patch-*.xml ; do
            if [ -f "$PATCHFILE" ] ; then
  	      PATCHID=`grep -i patchid $PATCHFILE | cut -d '"' -f 2`
  	      PATCHNAME=${PATCHID%-*}
  	      PATCHNUMBER=${PATCHID##*-}
  	      KIND=""
  	      KIND=`grep '<category>' "$PATCHFILE" | cut -d '>' -f 2 | cut -d '<' -f 1`
  	      PATCHBUNDLE="${PATCHID}"
              if echo "$EXISTING_PATCHES" | grep "$PATCHBUNDLE" - 2>/dev/null 1>&2 ; then
		echo "Patch "$PATCHBUNDLE" was already processed correctly - skipping."
  	      else
  	        START=`grep -n '<description lang="en">' "$PATCHFILE" | cut -d ':' -f 1`
  	        GOODSTART=`expr $START + 1`
  	        START2=`tail +${GOODSTART} "$PATCHFILE" | grep -n  '</description>' | head  -1 | cut -d ':' -f 1`
  	        GOODEND=`expr $START + $START2 - 1`
	        PATCHINFOID=`grep 'PATCHINFO' "$PATCHFILE" | cut -d '"' -f 2`
  	        DESCRIPTION=`sed -n "$START,${GOODEND}p" "$PATCHFILE" | cut -d '>' -f 2 | tr -d '\r\n' `
	        DESCRIPTION_FILTERED=`echo $DESCRIPTION | tr -d '\'`
	        TOTALDESCRIPTION="$PATCHINFOID"" - ""$DESCRIPTION_FILTERED"
  	        if $YUP2ZLM_ZLMAN_CMD bc "$PATCHBUNDLE" "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH" --description="$TOTALDESCRIPTION" ; then
		  :
  	        else
	          $YUP2ZLM_ZLMAN_CMD bd "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE"
		  if $YUP2ZLM_ZLMAN_CMD bc "$PATCHBUNDLE" "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH" --description="$TOTALDESCRIPTION" ; then
		    echo Replaced uncommitted bundle "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" 
 		  else
  	            echo Could not create bundle "$PATCHBUNDLE" in folder "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH".
  	            THIS_ARCH_OK="false"
  	            break
		  fi
  	        fi
                patchbundleok=true
	        ATOMLIST=""
	        for ATOM in `cat "$PATCHFILE" | grep atom | grep rpm | cut -d '"' -f 4,8,10 | tr '"' '-'` ; do
                  for ATOMFILE in `ls ../rpm/*/$ATOM*.rpm` ; do
                    if echo "$ATOMFILE" | grep -i 'patch.rpm$' -  ; then
		      echo Skipping patch rpm $ATOMFILE
		    else
		      if ls $ATOMFILE ; then
		        ATOMLIST="$ATOMLIST $ATOMFILE"
		      else
           	        echo Could not locate rpm corresponding to atom "$ATOM".
    		        patchbundleok=false
		        break
		      fi
 		    fi
		  done
		  if [ "$patchbundleok" = "false" ] ; then
	            break
		  fi
	        done
	        if [ "$patchbundleok" = "false" ] ; then
                  THIS_ARCH_OK="false"
                  break 
                fi
                if echo "$PATCHID" | grep 'kernel-' ; then
	          if $YUP2ZLM_ZLMAN_CMD bap --force-nevra  --installtype=install "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" $PRODARCH $ATOMLIST ; then
		    echo Added rpms "$ATOMLIST" to bundle "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" .
		  else
  		    echo Could not add rpm "$ATOM*.rpm" to bundle "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" . 
		    THIS_ARCH_OK="false"
		    break 
		  fi
	        else 
	          if $YUP2ZLM_ZLMAN_CMD bap --force-nevra  --freshen --installtype=upgrade "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" $PRODARCH $ATOMLIST ; then
		    echo Added rpms "$ATOMLIST" to bundle "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" .
		  else
  		    echo Could not add rpm "$ATOM*.rpm" to bundle "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$PATCHBUNDLE" . 
		    THIS_ARCH_OK="false"
		    break 
		  fi
 	        fi
	        ADD_LIST=""
  	        case "$KIND" in
  	        security)
		  if echo "$PATCHID" | grep 'kernel-' ; then
		    echo Skipping kernel patch "$PATCHID" as security patch and adding it to kernel security patches. 
                    ADD_LIST="$ADD_LIST $YUP2ZLM_KER_SEC_PATCH_BUNDLE_EXT"
                  else
                    ADD_LIST="$ADD_LIST $YUP2ZLM_SEC_PATCH_BUNDLE_EXT"
	          fi
  		  ;;
  	        recommended)
		  if echo "$PATCHID" | grep 'kernel-' ; then
		    echo Skipping kernel patch "$PATCHID" as recommended patch and adding it to kernel non-security patches. 
                    ADD_LIST="$ADD_LIST $YUP2ZLM_KER_NONSEC_PATCH_BUNDLE_EXT"
                  else
                    ADD_LIST="$ADD_LIST $YUP2ZLM_REC_PATCH_BUNDLE_EXT"
	          fi
  		  ;;
  	        *)
		  if echo "$PATCHID" | grep 'kernel-' ; then
		    echo Skipping kernel patch "$PATCHID" as optional patch and adding it to kernel non-security patches. 
                    ADD_LIST="$ADD_LIST $YUP2ZLM_KER_NONSEC_PATCH_BUNDLE_EXT"
                  else
                    ADD_LIST="$ADD_LIST $YUP2ZLM_OPT_PATCH_BUNDLE_EXT"
	          fi
  	  	  ;;
  	        esac
	        EXTENSION=""
	        for EXTENSION in $ADD_LIST ; do
  	          if $YUP2ZLM_ZLMAN_CMD bga "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$EXTENSION"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH"  "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"${PATCHBUNDLE}" ; then
		    :
  	          else
  	            echo Could not add patch ${PATCHID} to bundle "$EXTENSION"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" in folder "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH".
  	            THIS_ARCH_OK="false"
  	            break
  	          fi
		  for ENVIRONMENT in "$ENV_LOAD" ; do
		    if [ -n "$ENVIRONMENT" ] ; then
                      for DEVICE_KIND in `echo $DEVICE_GROUPS | tr ',' ' '` ; do
		        if [ -n "$DEVICE_KIND" ] ; then
		          if $YUP2ZLM_ZLMAN_CMD bga "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"/"$ARCH"/"$ENVIRONMENT"/"$DEVICE_KIND"_"$ENVIRONMENT"_"$EXTENSION"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH"  "$CURRENTFOLDER"/"${PATCHBUNDLE}" ; then
                            :
                          else
                            echo Could not add patch ${PATCHID} to bundle "$DEVICE_KIND"_"$ENVIRONMENT"_"$EXTENSION"_"$YUP2ZLM_PATCH_BUNDLE_BASE_NAME"_"$PRODARCH" in folder "$CURRENTFOLDER"/"$DEVICE_KIND"/"$PRODUCT"/"$ARCH"/"$ENVIRONMENT".
                            THIS_ARCH_OK="false"
                            break 
                          fi
		        fi
		      done
		    fi
                    if [ "$THIS_ARCH_OK" = "false" ] ; then
		      break
                    fi
		  done
                  if [ "$THIS_ARCH_OK" = "false" ] ; then
		    break
                  fi
	        done
                if [ "$THIS_ARCH_OK" = "false" ] ; then
                  break
                fi
	        if $YUP2ZLM_ZLMAN_CMD bc "$PATCHBUNDLE" "$CURRENTFOLDER"/"$PRODUCT"/"$ARCH"/"$YUP2ZLM_TRANS_FOLDER" ; then
	        :
	        else
	          echo Could not add patch "$PATCHBUNDLE" to transaction folder.
	          THIS_ARCH_OK="false"
	          break
	        fi
              fi
  	    fi
# ----------------------------------------------------------------------------------------------------------------------
# ------------------------------- Patch was processed correctly - adding to transacion log folder ... ------------------
# ----------------------------------------------------------------------------------------------------------------------
          done
	fi
        if [ "$THIS_ARCH_OK" = "false" ] ; then
          echo Errors found - skipping architecture "$ARCH" for product "$PRODUCT".
  	  continue
        fi
      else
        echo REFUSED ARCH : "$ARCH"
      fi
    done
  else
    echo REFUSED PRODUCT : "$PRODUCT_FOLDER"
  fi
done

