#!/bin/bash
#< Configure Processor Pool for zone implementation (Solaris 10)

AWK="/usr/bin/awk"
BASENAME="/usr/bin/basename"
ECHO="/bin/echo"
GREP="/usr/xpg4/bin/grep"
ID="/usr/xpg4/bin/id"
POOLADM="/usr/sbin/pooladm"
POOLCFG="/usr/sbin/poolcfg"
PRIOCNTL="/usr/bin/priocntl"
PS="/usr/bin/ps"
SED="/usr/bin/sed"
SVCS="/usr/bin/svcs"

THISPROG=$( ${BASENAME} $0 )

function print_error {
   ${ECHO} "Error: $@" >&2
}

function print_msg {
   ${ECHO} "--> $@"
}

function print_usage {
   ${ECHO} "Usage: ${THISPROG}"
}

function get_id {
   MY_UID=$( ${ID} -un )
   if [ "${MY_UID}" != "root" ]; then
      print_error "This script must be run as root"
      exit 1
   fi
}

function check_pools_enabled {
   POOL_STATE=$( ${SVCS} svc:/system/pools:default | ${AWK} 'NR==2 {print $1}' )
   if [ "${POOL_STATE}" = "online" ]; then
      print_msg "svc:/system/pools:default already enabled"
   elif [ "${POOL_STATE}" = "disabled" ]; then
      print_msg "svc:/system/pools:default disabled - enabling..." 
      ${POOLADM} -e
      ${POOLADM} -s
      ${POOLADM} -c
      if [ "$?" -eq "0" ]; then
         print_msg "svc:/system/pools:default enabled"
      else
         print_error "Unable to enable svc:/system/pools:default"
         exit 1
      fi
   else
      print_error "svc:/system/pools:default in state ${POOL_STATE}"
      print_msg "I do not know how to handle that - fix manually"
      exit 1
   fi
}

function check_current_configuration {
   # assumption: if the zone-{pset,pool} resources do not exist, then
   #             we're safe to do our thing...
   ERROR_COUNT=0
   ${POOLADM} | ${GREP} -q "zone_pset"
   if [ "$?" -eq "0" ]; then
      print_error "zone-pset already exists in resource configuration"
      (( ERROR_COUNT = ERROR_COUNT + 1 ))
   fi
   ${POOLADM} | ${GREP} -q "zone_pool"
   if [ "$?" -eq "0" ]; then
      print_error "zone-pool already exists in resource configuration"
      (( ERROR_COUNT = ERROR_COUNT + 1 ))
   fi
   if [ "${ERROR_COUNT}" -gt "0" ]; then
      exit 1
   fi
}

function set_default_ts {
   ${POOLCFG} -c 'modify pool pool_default ( string pool.scheduler="TS" )'
   ${POOLADM} -c
}

function convert_ts {
   ${PRIOCNTL} -s -c TS -i class FSS
   ${PRIOCNTL} -s -c TS -i pid 1
}

function switch_default_to_ts {
   POOL_DEFAULT=$( ${POOLADM} | ${SED} -n '/pool pool_default/,/pset_default/ p' )
   ${ECHO} "${POOL_DEFAULT}" | ${GREP} -q "pool.sched"
   if [ "$?" -ne "0" ]; then
      # no pool.scheduler set - so we'll explicitly set to TS anyway
      print_msg "WARNING: Could not find pool_default pool.scheduler - proceeding anyway..."
      set_default_ts
   else
      POOL_SCHED=$( ${ECHO} "${POOL_DEFAULT}" | ${GREP} "pool.sched" | ${AWK} '{print $NF}' )
      if [ "${POOL_SCHED}" = "FSS" ]; then
         print_msg "Converting pool_default from FSS to TS scheduling"
         set_default_ts
         convert_ts
      elif [ "${POOL_SCHED}" = "TS" ]; then
         print_msg "pool_default already in TS scheduling class"
      else
         print_error "pool_default has scheduling class ${POOL_SCHED}"
         print_msg "I do not know how to handle that - fix manually"
         exit 1
      fi
   fi
}

function create_zone_resources {
   print_msg "Creating zone_pset - pset.min=2 pset.max=15"
   ${POOLCFG} -c 'create pset zone_pset ( uint pset.min=2; uint pset.max=15 )'
   print_msg "Creating zone_pool"
   ${POOLCFG} -c 'create pool zone_pool'
   print_msg "Associating zone_pset with zone_pool"
   ${POOLCFG} -c 'associate pool zone_pool ( pset zone_pset )'
   print_msg "Setting zone_pool to FSS scheduling class"
   ${POOLCFG} -c 'modify pool zone_pool ( string pool.scheduler="FSS" )'
   ${POOLADM} -c
   print_msg "Done configuring zone resources"
}

if [ "$#" -ne "0" ]; then
   print_usage && exit 1
fi

get_id
check_pools_enabled
check_current_configuration
switch_default_to_ts
create_zone_resources

exit 0