#!/bin/bash # setup_processor_group.sh # To setup processor groups on Linux and Solaris. CREATE_STX="-name -numa_nodes | -cpus " DELETE_STX="-name " USAGE="Usage: setup_processor_group.sh [command] [options] Commands: -prepare Prepare the system for processor groups This sets up the system for processor groups usage and gives the relevant permissions to oracle user to be able to create and use the processor groups. This needs to be run as root. -create Create a processor group. Options syntax: $CREATE_STX -name This option specifies the processor group name. -numa_nodes This option specifies the NUMA nodes for this processor group. The processor group will include all CPUs from these NUMA nodes. Cannot be combined with -cpus option. -cpus This option specifies the CPUs for this processor group. No numa affinity for the nodes is assigned for this processor group. Cannot be combined with -numa_nodes option. -delete Delete a processor group. Options syntax: $DELETE_STX -name This option specifies the processor group name. -show Print the CPU configuration and NUMA node configuration and the existing processor groups. -help Print this usage message. Notes: ----- Start with preparing the system for processor group setup by running as root: $ setup_processor_group.sh -prepare To look at the your current processor group configuration: $ setup_processor_group.sh -show To create a processor group pgroup23 with numa nodes 2 and 3 as follows: $ setup_processor_group.sh -create -name pgroup23 -numa_nodes 2,3 To create a processor group pgroup1234 with cpus 1,2,3 and 4 as follows: $ setup_processor_group.sh -create -name pgroup1234 -cpus 1,2,3,4 To delete a processor group: $ setup_processor_group.sh -delete -name pgroup1234 To start an Oracle instance in the processor group pgroup23, add the following init.ora parameter: PROCESSOR_GROUP_NAME=pgroup23 " PATH="/usr/gnu/bin:/bin:/usr/bin:/sbin:/usr/sbin" export PATH LINUX=1 SOLARIS=2 # os - The OS, 1:Linux, 2:Solaris os=0 # USAGE: check_return expected_value exit_message # Check the return value and exit on error. function check_return { RETURN_STATUS=$? EXP_VALUE=$1; shift EXIT_MESSAGE=$1; shift if [ "$RETURN_STATUS" -ne "$EXP_VALUE" ] then echo "Expected status $EXP_VALUE got ${RETURN_STATUS}." echo "$EXIT_MESSAGE" exit 1 fi } # USAGE: syntax_message message command # Print the syntax and exit. function syntax_message { MESSAGE=$1; shift COMMAND=$1; shift echo "$MESSAGE;" if [[ $COMMAND == "create" ]] then echo "-create command options syntax:" echo "$CREATE_STX" elif [[ $COMMAND == "delete" ]] then echo "-delete command options syntax:" echo "$DELETE_STX" fi exit "1" } # get_os - Get the OS, Linux or Solaris. function get_os() { local os_string; os_string=`uname`; if [[ "$os_string" == "Linux" ]]; then os=$LINUX; else if [[ "$os_string" == "SunOS" ]]; then os=$SOLARIS; else echo "# Error:" echo "# OS: $os_string. This script only works on Linux and Solaris." exit fi fi } # USAGE: solaris_prepare function solaris_prepare { return; } # USAGE: linux_prepare function linux_prepare { # create the cgroup directory and mount it. CGROUP_DIR=/dev/cgroup if [ ! -d "$CGROUP_DIR" ] then mkdir $CGROUP_DIR check_return 0 "Cannot make $CGROUP_DIR dir" fi # Change ownership to oracle user. chown -R oracle $CGROUP_DIR check_return 0 "Cannot change owner of $CGROUP_DIR dir to oracle" mount -t cgroup cpuset -ocpuset $CGROUP_DIR check_return 0 "Cannot mount $CGROUP_DIR dir" } # USAGE: solaris_create_nodes name node_list # node_list must be a comma seperated list function solaris_create_nodes { return; } # USAGE: linux_create_nodes name node_list # node_list must be a comma seperated list function linux_create_nodes { NAME=$1 NODES=$2 NODE_LIST=$(echo $NODES | awk -F"," '{$1=$1; print}') CGROUP_DIR=/dev/cgroup # cretae and mount the cgroup dir if [ ! -d "$CGROUP_DIR" ] then echo "/dev/cgroup not mounted" echo "Please run this script with -prepare option as root before doing this." exit "1" fi cd $CGROUP_DIR check_return 0 "Cannot cd to $CGROUP_DIR" if [ -d "$NAME" ] then echo "Processor group $NAME already exists. Delete it to create this." exit "1" else mkdir $NAME check_return 0 "Cannot make directory $CGROUP_DIR/$NAME" chown -R oracle $CGROUP_DIR check_return 0 "Cannot change owner of $CGROUP_DIR/$NAME dir to oracle" fi cd $NAME check_return 0 "Cannot cd to $CGROUP_DIR/$NAME" # collect the cpus for each node. for NODE in $NODE_LIST do NODE_CPULIST=`cat /sys/devices/system/node/node${NODE}/cpulist`; check_return 0 "Cannot get cpulist for node $NODE"; if [ ! -n "$CPULIST" ] then CPULIST="$NODE_CPULIST"; else CPULIST="$CPULIST,$NODE_CPULIST"; fi done # Add the cpus and mems to the cgroup /bin/echo $CPULIST > cpuset.cpus check_return 0 "Cannot write to $CGROUP_DIR/$NAME/cpuset.cpus; Check for valid syntax or permissions." /bin/echo $NODES > cpuset.mems check_return 0 "Cannot write to $CGROUP_DIR/$NAME/cpuset.mems; Check for valid syntax or permissions." echo "Succesfully added CPUs $CPULIST and NUMA nodes $NODES to processor group $NAME" } # USAGE: solaris_create_cpus name cpu_list # node_list must be a comma seperated list of numbers or ranges function solaris_create_cpus { return; } # USAGE: linux_create_cpus name cpu_list # node_list must be a comma seperated list of numbers or ranges function linux_create_cpus { NAME=$1 CPULIST=$2 CGROUP_DIR=/dev/cgroup if [ ! -d "$CGROUP_DIR" ] then echo "/dev/cgroup not mounted" echo "Please run this script with -prepare option as root before doing this." exit "1" fi cd $CGROUP_DIR check_return 0 "Cannot cd to $CGROUP_DIR" if [ -d "$NAME" ] then echo "processor group $NAME already exists. Delete it to create this." exit "1" else mkdir $NAME check_return 0 "Cannot make directory $CGROUP_DIR/$NAME" chown -R oracle $CGROUP_DIR check_return 0 "Cannot change owner of $CGROUP_DIR/$NAME dir to oracle" fi cd $NAME check_return 0 "Cannot cd to $CGROUP_DIR/$NAME" # Add the cpus and mems to the cgroup /bin/echo $CPULIST > cpuset.cpus check_return 0 "Cannot write to $CGROUP/$NAME/cpuset.cpus; Check for valid syntax or permissions." NODES=`cat $CGROUP_DIR/cpuset.mems` /bin/echo $NODES > cpuset.mems check_return 0 "Cannot write to $CGROUP_DIR/$NAME/cpuset.mems; Check for valid syntax or permissions." echo "Succesfully added CPUs $CPULIST to processor group $NAME" } #USAGE solaris_delete name function solaris_delete { return; } #USAGE linux_delete name function linux_delete { NAME=$1 CGROUP_DIR=/dev/cgroup/$NAME if [ ! -d "$CGROUP_DIR" ] then echo "processor group $NAME does not exist." exit "1" fi # deleting the cgroup is deleting the directory. rmdir $CGROUP_DIR check_return 0 "cannot rmdir $CGROUP_DIR; processor group $NAME cannot be deleted." echo "Succesfully deleted processor group $NAME" } # USAGE solaris_show function solaris_show { return; } # USAGE linux_show function linux_show { if [ -d "/sys/devices/system/node" ] then count=0 echo "This is a NUMA system." echo "" # print NUMA configuration echo "NUMA configuration:" echo "-------------------" while [[ $count != "-1" ]] do if [ -d "/sys/devices/system/node/node$count" ] then echo "Node $count" cpus=`cat "/sys/devices/system/node/node$count/cpulist"` echo " CPUs: $cpus" mem=`cat "/sys/devices/system/node/node$count/meminfo" |grep MemT | awk -F":" '{$1=$1; print}'` set $mem; total="$4 $5" mem=`cat "/sys/devices/system/node/node$count/meminfo" |grep MemF | awk -F":" '{$1=$1; print}'` set $mem; free="$4 $5" echo " Memory Total: $total Free: $free" count=`expr $count + 1` else count=-1 fi done else echo "This is not a NUMA system." echo "" CPU_LIST=`cat /proc/cpuinfo |grep processor |sed "s/processor//g" |sed "s/://g"` set $CPU_LIST; CPU_FIRST=$1; for CPU in $CPU_LIST do CPU_LAST=$CPU done echo "CPUs on this system:" echo " $CPU_FIRST-$CPU_LAST" mem=`cat "/proc/meminfo" |grep MemT | awk -F":" '{$1=$1; print}'` set $mem; total="$2 $3" mem=`cat "/proc/meminfo" |grep MemF | awk -F":" '{$1=$1; print}'` set $mem; free="$2 $3" echo " Memory Total: $total Free: $free" fi echo "" # check if cgroups are setup if [ -d "/dev/cgroup" ] then # check mounts mount=`mount|grep cgroup` set $mount if [[ $1 != "cpuset" ]] then echo "WARNING: This system is not prepared for processor groups." echo "WARNING: Run setup_processor_group.sh -prepare as root" return; fi # check permissions F=`ls -G -l -F /dev |grep '/' | grep cgroup`;set $F; if [[ $3 != "oracle" ]] then echo "WARNING: This system is not prepared for processor groups." echo "WARNING: Run setup_processor_group.sh -prepare as root" return; fi CG_LIST=$(echo `ls -F /dev/cgroup |grep '/'` | awk -F"/" '{$1=$1; print}') echo "Processor groups on this system:" echo "--------------------------------" for CG in $CG_LIST do echo "$CG" echo " nodes: `cat /dev/cgroup/$CG/cpuset.mems`" echo " cpus: `cat /dev/cgroup/$CG/cpuset.cpus`" done else echo "WARNING: This system is not prepared for processor groups." echo "WARNING: Run setup_processor_group.sh -prepare as root" fi } # main if [ $# -eq 0 ] then echo "$USAGE" exit "1" fi get_os CMD=$1; shift case "$CMD" in -create) # -name -numa_nodes|-cpus while [ $# -ne 0 ] do OPTION="$1";shift case "$OPTION" in -name) NAME="$1";shift ;; -numa_nodes) NODES="$1";shift ;; -cpus) CPUS="$1";shift ;; *) syntax_message "Unexpected option $OPTION" $CMD ;; esac done if [[ -z $NAME ]] then syntax_message "-name option required" "create" fi if [[ -z $NODES && -z $CPUS ]] then syntax_message "-numa_nodes or -cpus option required" "create" fi if [[ -n $NODES && -n $CPUS ]] then syntax_message "Cannot specify both -numa_nodes and -cpus options" "create" fi if [[ -n $NODES ]] then NODE_LIST=$(echo $NODES | awk -F"," '{$1=$1; print}') #check the node list syntax for NODE in $NODE_LIST do if [[ $NODE != "${NODE//[^0-9]/}" ]] then syntax_message "-numa_nodes should be followed by a comma seperated list of numbers" "create" fi done if [[ "$os" == "$LINUX" ]]; then linux_create_nodes $NAME $NODES else solaris_create_nodes $NAME $NODES fi fi if [[ -n $CPUS ]] then CPU_LIST=$(echo $CPUS | awk -F"," '{$1=$1; print}') if [[ "$os" == "$LINUX" ]]; then linux_create_cpus $NAME $CPUS else solaris_create_cpus $NAME $CPUS fi fi echo "To start an Oracle instance in this processor group, add the following to the init.ora parameter file:" echo "PROCESSOR_GROUP_NAME=$NAME" ;; -delete) # -name " NBR_ARGS=2 if [ $# -ne $NBR_ARGS ] then syntax_message "Wrong number of arguments" "delete" fi OPTION="$1";shift if [[ $OPTION != "-name" ]] then syntax_message "-name option must be specified" "delete" fi NAME="$1";shift if [[ "$os" == "$LINUX" ]]; then linux_delete $NAME else solaris_delete $NAME fi ;; -prepare) #Make sure it is run as root if [[ $EUID -ne 0 ]]; then echo "This command must be run as root" exit "1" fi if [[ "$os" == "$LINUX" ]]; then linux_prepare else solaris_prepare fi ;; -show) if [[ "$os" == "$LINUX" ]]; then linux_show else solaris_show fi ;; -help) echo "$USAGE" ;; *) echo "Unknown command $CMD" echo "$USAGE" ;; esac exit "0"