#!/bin/sh
#
# rep_populate.sh
#
# Updated: 4/28/2011

# Command paths
UP2DATE=/usr/sbin/up2date
YUM=/usr/bin/yum
CREATEREPO=/usr/bin/createrepo
YUMARCH=/usr/bin/yum-arch
REPOSYNC=/usr/bin/reposync
MODIFYREPO=/usr/bin/modifyrepo
GUNZIP=/bin/gunzip

# yum repository paths
REP_BASE=/var/www/html/yum
REP_EL=EnterpriseLinux
REP_OL=OracleLinux
REP_OVM=OracleVM
REP_UNK=unknown

# channel list command
CHAN_LIST=/tmp/chan_list.py

# Maximum number of packages to download at once
MAXPKG=1000

# The script has the option to be able to download the src rpms alongside
# the binary rpms.  The default, however is to NOT download them.  So, set the
# default and then check if the user asked for the src rpms.
SRC=0
if [ $# -eq 1 ] ; then
  if [ "$1" = "src" ] ; then
    SRC=1
  else
    echo "$0: unknown argument \"$1\""
    echo "usage: $0 [src]"
    exit 1
  fi
fi

# Identify what OS the script is running on.
# If the OS is EL or RHEL, save version and arch info.
if rpm -q --whatprovides redhat-release >/dev/null 2>&1
then
  EL_VER=`rpm -qf /etc/redhat-release --qf '%{VERSION}' | sed 's/[^0-9]*//g'`
  EL_ARCH=`uname -i`
else
  echo "Error: script must be run on Enterprise Linux OS"
  exit 1
fi

# set the prefix (OL/EL)
case $EL_VER in
    6)
        [ $SRC -eq 1 ] && SRCARG="--source" || SRCARG=""
        rm -rf /var/cache/yum/* >/dev/null 2>&1
        ADDONS=ol${EL_VER}_${EL_ARCH}_addons
        LATEST=ol${EL_VER}_${EL_ARCH}_latest
        YUM_PROXY_INST_CMD="$YUM install uln-yum-proxy -y --disablerepo=* --enablerepo=${ADDONS},${LATEST}"
        CREATEREPO_EXTRA_ARGS="-d --update -s sha"
        ;;
    5)
        [ $SRC -eq 1 ] && SRCARG="--src" || SRCARG="--nosrc"
        rm -rf /var/spool/up2date/* >/dev/null 2>&1
        ADDONS=el${EL_VER}_${EL_ARCH}_addons
        LATEST=ol${EL_VER}_${EL_ARCH}_latest
        YUM_PROXY_INST_CMD="$UP2DATE -i uln-yum-proxy --channel ${ADDONS} --channel ${LATEST}"
        CREATEREPO_EXTRA_ARGS="-d --update"
        ;;
    4)
        [ $SRC -eq 1 ] && SRCARG="--src" || SRCARG="--nosrc"
        rm -rf /var/spool/up2date/* >/dev/null 2>&1
        ADDONS=el${EL_VER}_${EL_ARCH}_addons
        LATEST=el${EL_VER}_${EL_ARCH}_latest
        YUM_PROXY_INST_CMD="$UP2DATE -i uln-yum-proxy --channel ${ADDONS} --channel ${LATEST}"
        ;;
    *)
        echo "Error: unsupported version ($EL_VER)"
        exit 1
        ;;
esac

# Install uln-yum-proxy if missing.
# This installs packages required to create yum repositories.
rpm -q uln-yum-proxy >/dev/null 2>&1 || $YUM_PROXY_INST_CMD

# If uln-yum-proxy did not get installed, abort.
if ! rpm -q uln-yum-proxy >/dev/null 2>&1
then
  echo "Error installing uln-yum-proxy... aborting."
  exit 1
fi

# easiest way to get the list of channel labels is direct from ULN via python
# so lets write a simple python utility locally so that we can get the info
(
cat << 'EOF'
#!/usr/bin/python
import sys
sys.path.append('/usr/share/rhn/')
from up2date_client import up2dateAuth,rpcServer
sid = up2dateAuth.getSystemId()
if sid is None:
    print "Error: system not registered"
    sys.exit(-1)
try:
    s = rpcServer.getServer()
    for chan in [x['label'] for x in s.up2date.listChannels(sid)]:
        print chan
except:
    print "Error: ", sys.exc_info()[1].faultString
    sys.exit(-1)
EOF
) > $CHAN_LIST

chmod 777 $CHAN_LIST

${CHAN_LIST} | sort | while read CHANNEL ; do
  echo "## BEGIN PROCESSING $CHANNEL ##"
  # convert the channel label into a path suitable for our yum conventions
  DIR=`echo $CHANNEL | sed 's/x86_64/x86-64/g' |
  sed 's/_u\([0-9][0-9]*\)_/_\1_/' | awk -F _ '{ printf("%s/", toupper($1)); \
   count=1; while (++count<NF) \
   {if(count==NF-1) {print $(count+1)"/"$(count)} else \
   {printf("%s/", $(count))}}}' | sed 's/x86-64/x86_64/g'`

  # determine the correct yum repository directory
  REP_PATH=$REP_BASE/$REP_UNK/$DIR
  echo $CHANNEL | grep '^el[0-9]*_' >/dev/null 2>&1 && \
    REP_PATH=$REP_BASE/$REP_EL/$DIR
  echo $CHANNEL | grep '^ol[0-9]*_' >/dev/null 2>&1 && \
    REP_PATH=$REP_BASE/$REP_OL/$DIR
  echo $CHANNEL | grep '^ovm[0-9]*_' >/dev/null 2>&1 && \
    REP_PATH=$REP_BASE/$REP_OVM/$DIR

  echo "Channel Dir: $REP_PATH"

  # Create the required yum repository directory.
  # If directory creation failed, print error and exit.
  mkdir -p $REP_PATH
  if [ ! -d $REP_PATH ] ; then
    echo "There was an error creating $REP_BASE."
    echo "Please check the permissions of the directory tree to ensure"
    echo "that this directory can be created and then re-run this script."
    exit 1
  fi

  cd $REP_PATH

  if [[ $EL_VER -eq 6 ]] ; then
      # if the channel is an x86_64 channel and the mirror host is an x86 system
      # then we need to add the -a option to allow for the non-matching-arch rpms
      # to be found and downloaded
      if `echo ${channel} | grep -q x86_64` && [ x`uname -i`x == 'xi386x' ] ; then
          srcarg="${srcarg} -a x86_64"
      fi
      ${REPOSYNC} -l -m -p ${REP_PATH} -r ${CHANNEL} --norepopath --download-metadata ${SRCARG} 
  else
      # tmp files
      TMPOLDCHAN=/tmp/${CHANNEL}.old
      TMPNEWCHAN=/tmp/${CHANNEL}.new

      # Always set --nosrc for oracle channels, which has no src rpms
      echo $CHANNEL | grep "_oracle$" >/dev/null 2>&1 && SRCARG="--nosrc"
      echo $CHANNEL | grep "_addons$" >/dev/null 2>&1 && SRCARG="--nosrc"

      # figure out which rpms are new
      ${UP2DATE} --showall --channel ${CHANNEL} | sort > ${TMPNEWCHAN}

      # figure out which rpms are there currently
      find ${REP_PATH} -name "*rpm" -type f 2> /dev/null | \
        sed -e 's/^.*.\///' -e 's/\.rpm$//' | sort > ${TMPOLDCHAN}

      if [ -e ${TMPOLDCHAN} ] ; then
          CMD="comm -23 ${TMPNEWCHAN} ${TMPOLDCHAN}"
      else
          CMD="cat ${TMPNEWCHAN}"
      fi

      # actually get the rpms
      $CMD | xargs -n $MAXPKG \
        ${UP2DATE} --nox --get ${SRCARG} --download --tmpdir=. --channel ${CHANNEL}
      
      # Clean up download dir.  Only keep rpms.
      find . -type f -not -name "*rpm" -exec rm -f {} \;
      
      # move src rpms to SRPMS directory
      if [ $SRC -eq 1 ] ; then
          mkdir -p SRPMS
          mv *.src.rpm SRPMS
      fi

      rm -f $TMPOLDCHAN $TMPNEWCHAN
  fi
      
  # run createrepo command if present
  if [ -x $CREATEREPO ] ; then
      GRPARG=
      if [ -f ${REP_PATH}/comps.xml ] ; then
          GRPARG="-g ${REP_PATH}/comps.xml"
      fi
      ${CREATEREPO} -c ${REP_PATH}/.cache $GRPARG $CREATEREPO_EXTRA_ARGS $REP_PATH

      # if there's an updateinfo file for this repo, then patch it into the repo info
      if [ -f ${REP_PATH}/updateinfo.xml.gz ] ; then
          ${GUNZIP} -q ${REP_PATH}/updateinfo.xml.gz
          ${MODIFYREPO} ${REP_PATH}/updateinfo.xml ${REP_PATH}/repodata/
      fi
  else
      echo "${CREATEREPO}: command not found"
  fi

  # run yum-arch command if present
  if [ -x ${YUMARCH} ] ; then
    if [ ${SRC} -eq 1 ] ; then
      ${YUMARCH} -s $REP_PATH 2>/dev/null
    else
      ${YUMARCH} $REP_PATH 2>/dev/null
    fi
  else
    echo "${YUMARCH}: command not found"
  fi
  echo "## END PROCESSING $CHANNEL ##"
done

rm -f $CHAN_LIST
