mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-30 19:02:27 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			382 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			382 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| # IBM(c) 2017 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| #(C)IBM Corp
 | |
| #
 | |
| ###################################################################
 | |
| #
 | |
| # Description:
 | |
| #     This script is used for performance testing purpose. It could
 | |
| #     generate n*250 fake nodes based on a predefined template (/opt/xcat/share/xcat/templates/objects/node/),
 | |
| #     and then run the performance testing on a batch of xCAT commands.
 | |
| #
 | |
| #     Note: It is availabe for the commands which require management node only. 
 | |
| #
 | |
| # Syntax:
 | |
| #       $prog <total> [command-list-file]
 | |
| #
 | |
| ###################################################################
 | |
| 
 | |
| if [ -z $LC_ALL ]; then
 | |
|   export LC_ALL=C
 | |
| fi
 | |
| 
 | |
| # Used for number parameter validation
 | |
| isNumber()
 | |
| {
 | |
|   expr $1 + 0 &>/dev/null
 | |
| }
 | |
| 
 | |
| # Used for prerequiste checking
 | |
| preChecking()
 | |
| {
 | |
|   local val=""
 | |
|   for cmd in brctl ifconfig; do
 | |
|     which $cmd  > /dev/null 2>&1
 | |
|     [  $? -ne 0 ] && val="$cmd,$val"
 | |
|   done
 | |
|   echo $val | sed s/,$//
 | |
| }
 | |
| 
 | |
| # Give a simple usage
 | |
| if [ -z "$1" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
 | |
|   echo "[PERF_DRYRUN=y] [PERF_NOCREATE=y] $0 <total> [command-list-file]"
 | |
|   exit
 | |
| else
 | |
|   isNumber $1
 | |
|   if [ ! $? -eq 0 ]; then
 | |
|      echo "You must input an numeric string for total nodes number."
 | |
|      exit -1
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| # Source xCAT profile to make sure the xCAT commands could be executed without absolute path.
 | |
| if [ -z $XCATROOT ]; then
 | |
|   if [ -r /etc/profile.d/xcat.sh ]; then
 | |
|     . /etc/profile.d/xcat.sh
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| pass=$(preChecking)
 | |
| if [ ! -z "$pass" ]; then
 | |
|   echo "Error: Missing required tools: $pass"
 | |
|   [ -z $PERF_DRYRUN ] && exit -1
 | |
| fi
 | |
| 
 | |
| # Mandatory, to specify the number of total fake nodes which will be created for testing
 | |
| FAKE_NODE_TOTAL=$1
 | |
| 
 | |
| # Optional, the prefix of the fake compute node name. 
 | |
| # By default, it is 'fake' but it could be changed when you set environment variable `FAKE_NODE_PREFIX`
 | |
| if [ -z $FAKE_NODE_PREFIX ]; then
 | |
|   FAKE_NODE_PREFIX='fake'
 | |
| fi
 | |
| 
 | |
| # Optional, the group name of all the fake compute nodes. 
 | |
| # By default, it is 'perftest' but it could be changed when you set environment variable `FAKE_NODE_GROUP`
 | |
| if [ -z $FAKE_NODE_GROUP ]; then
 | |
|   FAKE_NODE_GROUP='perftest'
 | |
| fi
 | |
| 
 | |
| # Mandatory, the Provision network for all the fake compute nodes. It must be a string like 'A.B', and be matched with `tabdump networks`
 | |
| # By default, it is '192.168' but it could be changed when you set environment variable `FAKE_NETWORK_PRO`
 | |
| if [ -z $FAKE_NETWORK_PRO ]; then
 | |
|   FAKE_NETWORK_PRO='192.168'
 | |
| fi
 | |
| 
 | |
| # Mandatory, the BMC network for all the fake compute nodes. It must be a string like 'A.B' and no need to be defined in 'networks' table.
 | |
| # By default, it is '192.169' but it could be changed when you set environment variable `FAKE_NETWORK_BMC`
 | |
| # Note:  it could not be the same subnet as 'FAKE_NETWORK_PRO'
 | |
| if [ -z $FAKE_NETWORK_BMC ]; then
 | |
|   FAKE_NETWORK_BMC='192.169'
 | |
| fi
 | |
| 
 | |
| # Optional, The network mask for the fake network object.
 | |
| # By default, it is '255.255.0.0' but it could be changed when you set environment variable `FAKE_NETWORK_MASK`
 | |
| if [ -z $FAKE_NETWORK_MASK ]; then
 | |
|   FAKE_NETWORK_MASK='255.255.0.0'
 | |
| fi
 | |
| 
 | |
| # Optional, The bridge device name for the temporary interface which is required on MN as nodeset/makedhcp will check if the MN and CN in same subnet.
 | |
| # By default, it is 'perfvirbr0' but it could be changed when you set environment variable `FAKE_NETWORK_INTF`
 | |
| if [ -z $FAKE_NETWORK_INTF ]; then
 | |
|   FAKE_NETWORK_INTF='perfvirbr0'
 | |
| fi
 | |
| 
 | |
| # Optional, The node template name used for generating fake nodes.
 | |
| # By default, it is '<arch>-template' but it could be changed when you set environment variable `FAKE_NODE_GROUP`
 | |
| if [ -z $PERF_NODETEMPL ]; then
 | |
|   PERF_NODETEMPL="`arch`-template"
 | |
| fi
 | |
| 
 | |
| # IP address assinged to node will be in [1-250]
 | |
| NODE_PER_ROW=250
 | |
| MYSUFFIX=`date +"%Y%m%d%H%M%S"`
 | |
| 
 | |
| if [ -z $PERFORMANCE_DIR ]; then
 | |
|   PERFORMANCE_DIR=$XCATROOT/share/xcat/tools/autotest/result
 | |
| fi
 | |
| PERFORMANCE_NODE_TMPL=$PERFORMANCE_DIR/perf-node.tmpl
 | |
| PERFORMANCE_REPORT=$PERFORMANCE_DIR/perfreport-$FAKE_NODE_TOTAL.log.$MYSUFFIX
 | |
| PERFORMANCE_STANZ=$PERFORMANCE_DIR/perfstanz-$FAKE_NODE_TOTAL.$MYSUFFIX
 | |
| 
 | |
| # If the command list file is not specified, the tool will only create the stanz file for fake nodes.
 | |
| # If it is specified but not exists, the tool will exit with error.
 | |
| if [ ! -z $2 ]; then
 | |
|   if [ -f $2 ]; then
 | |
|     RUN_CMD_LIST=$2
 | |
|   else
 | |
|     echo "ERROR: The command list file you specified does not exist."
 | |
|     exit -1
 | |
|   fi
 | |
| fi
 | |
| 
 | |
| 
 | |
| # Get a random MAC address
 | |
| genMAC()
 | |
| {
 | |
|     printf '00:60:2F:%02X:%02X:%02X' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256]
 | |
| }
 | |
| 
 | |
| # Generate stanz file for all fake nodes
 | |
| genStanz()
 | |
| {
 | |
|   if [ ! -z $PERF_DRYRUN ]; then
 | |
|     echo $1, $2, $3, $4
 | |
|   else
 | |
|     echo -n .
 | |
|   fi
 | |
| 
 | |
|   sed -e '/Object name:/c \'"$1"':\n    objtype=node' \
 | |
|       -e '/ip=/c \    ip='"$3"'' \
 | |
|       -e '/mac=/c \    mac='"$2"'' \
 | |
|       -e '/bmc=/c \    bmc='"$4"'' \
 | |
|       -e '/bmcusername=/c \    bmcusername=fake' \
 | |
|       -e '/bmcpassword=/c \    bmcpassword=fake' \
 | |
|       -e '/groups=/c \    groups=all,'"$FAKE_NODE_GROUP"'' \
 | |
|       -e '/postscripts=/c \    postscripts=mypostboot' \
 | |
|       -e '/postbootscripts=/c \    postbootscripts=mypostboot' \
 | |
|       $PERFORMANCE_NODE_TMPL >> $PERFORMANCE_STANZ
 | |
| }
 | |
| 
 | |
| # Create a fake xCAT node definition
 | |
| fakeNode()
 | |
| {
 | |
|   # TODO: support regular expression for IP
 | |
|   genStanz $FAKE_NODE_PREFIX$1 $(genMAC) $FAKE_NETWORK_PRO.$2.$3 $FAKE_NETWORK_BMC.$2.$3
 | |
|   #mkdef -f -t node $FAKE_NODE_PREFIX$1 --template $PERF_NODETEMPL ip=$FAKE_NETWORK_PRO.$2.$3 mac=$(genMAC) \
 | |
|   #                bmc=$FAKE_NETWORK_BMC.$2.$3 bmcpassword=fake bmcusername=fake groups=all,performance > /dev/null 2>&1
 | |
| }
 | |
| 
 | |
| # Create a fake xCAT network definition
 | |
| fakeNetwork()
 | |
| {
 | |
|     lsdef -t network -o net-$FAKE_NODE_PREFIX > /dev/null 2>&1
 | |
|     if [ 0 != $? ]; then
 | |
|       mkdef -t network net-$FAKE_NODE_PREFIX net=$FAKE_NETWORK_PRO.0.0 mask=$FAKE_NETWORK_MASK > /dev/null
 | |
|     else
 | |
|       chdef -t network -o net-$FAKE_NODE_PREFIX net=$FAKE_NETWORK_PRO.0.0 mask=$FAKE_NETWORK_MASK > /dev/null
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # Create a fake xCAT network definition
 | |
| fakeInterface()
 | |
| {
 | |
|   result=`ifconfig $1 2>/dev/null`
 | |
|   if [ -z "$2" ]; then
 | |
|     [  -z "$result" ] && brctl addbr $1
 | |
|     ifconfig $1 $FAKE_NETWORK_PRO.251.254 netmask $FAKE_NETWORK_MASK || echo "$1 is not configured successfully"
 | |
|   elif [ ! -z "$result" ]; then
 | |
|     ifconfig $1 down
 | |
|     brctl delbr $1 || echo "$1 is not removed successfully, you may need to clean up manually."
 | |
|   fi
 | |
| }
 | |
| 
 | |
| getOSimage()
 | |
| {
 | |
|   # The OS image name used in nodeset to replace the MACRO Variable `#OSIMAGE#`.
 | |
|   # By default, it could be detectd automatically according to the arch
 | |
|   if [ -z $PERF_OSIMAGE ]; then
 | |
|     
 | |
|     # covert it to an array
 | |
|     osimage_array=($(lsdef -t osimage 2>/dev/null| grep `arch`|grep 'install'|awk '/compute/ {print $1}'))
 | |
|     index=`expr $RANDOM % ${#osimage_array[@]} 2>/dev/null`
 | |
|     echo ${osimage_array[$index]}
 | |
|   else
 | |
|     echo $PERF_OSIMAGE
 | |
|   fi
 | |
| }
 | |
| 
 | |
| # Create batch fake nodes stanz file for testing
 | |
| bootstrap()
 | |
| {
 | |
|   declare -i  count=0
 | |
|   [ $rack = 0 ] && rack=1
 | |
|   for i in $(seq 0 $(expr $rack - 1))
 | |
|   do
 | |
|     for j in $(seq 1 $NODE_PER_ROW)
 | |
|     do
 | |
|       count+=1
 | |
|       fakeNode $count $i $j
 | |
|       [ $(($count % $1)) = 0 ] && echo
 | |
|       [ "x$count" == "x$FAKE_NODE_TOTAL" ] && break
 | |
|     done
 | |
|   done
 | |
| }
 | |
| 
 | |
| # Get current time
 | |
| getTime()
 | |
| {
 | |
|   date +%s -d "$1"
 | |
| }
 | |
| 
 | |
| # Executing the testing on specific commands defined in command list file
 | |
| # All MACROs defined in command list file will be replaced with the real value
 | |
| runTest()
 | |
| {
 | |
| 
 | |
|   cmd=$1
 | |
|   [ -z $osimage ] || cmd="${cmd/\#OSIMAGE\#/$osimage}"
 | |
|   if [[ $cmd =~ '#STANZ#' ]]; then
 | |
|     #mkdef -z
 | |
|     execCmd "${cmd/\#STANZ\#/$PERFORMANCE_STANZ}" "$FAKE_NODE_TOTAL"
 | |
|   
 | |
|   elif [[ $cmd =~ '#NODES#' ]]; then
 | |
|     #noderange operation
 | |
|     if [ -z "$2" ]; then
 | |
|       # No SERIES defined, run command on the whole group
 | |
|       execCmd "${cmd/\#NODES\#/$FAKE_NODE_GROUP}" "$FAKE_NODE_TOTAL"
 | |
|     else
 | |
|       # run the command for each number in SERIES
 | |
|       for num in $2   
 | |
|       do
 | |
|         isNumber $num || continue
 | |
|         if [[ $num -le $FAKE_NODE_TOTAL ]]; then
 | |
|           #cmd=$1
 | |
|           execCmd "${cmd/\#NODES\#/$FAKE_NODE_PREFIX[1-$num]}" "$num"
 | |
|         fi
 | |
|       done
 | |
|     fi
 | |
|   elif [[ $cmd =~ '#PERFGRP#' ]]; then
 | |
|     execCmd "${cmd/\#PERFGRP\#/$FAKE_NODE_GROUP}" "$FAKE_NODE_TOTAL"
 | |
|   else
 | |
|     execCmd "$cmd" "N/A"
 | |
|   fi
 | |
| 
 | |
| }
 | |
| 
 | |
| # Output performance result for each command.
 | |
| printResult()
 | |
| {
 | |
|   #TODO,  more clear short desc for this command
 | |
|   desc=`echo "$1" | awk '{print $1}'`
 | |
|   result=$([[ $4 = 0 ]] && echo "SUCESS" || echo "FAIL")
 | |
|   # TOTAL, CMD, NODERANGE, TIME, SUCESS, FULL COMMAND
 | |
|   echo "$FAKE_NODE_TOTAL; $desc; $2; $3; $result; \"$1\"" | tee -a $PERFORMANCE_REPORT
 | |
| }
 | |
| 
 | |
| # Executing each command and print the result to report file
 | |
| execCmd()
 | |
| {
 | |
|   echo "Testing for [ $1 ] ..."
 | |
|   if [ ! -z $PERF_DRYRUN ]; then
 | |
|     return
 | |
|   fi
 | |
| 
 | |
|   starttime=`date +'%Y-%m-%d %H:%M:%S'`
 | |
|   start=$(getTime "$starttime")
 | |
|   eval "$1" > /dev/null 2>&1
 | |
|   retval=$?
 | |
|   endtime=`date +'%Y-%m-%d %H:%M:%S'`
 | |
|   end=$(getTime "$endtime")
 | |
| 
 | |
|   printResult "$1" "$2" "$(($end-$start))" "$retval"
 | |
| }
 | |
| 
 | |
| #################################################
 | |
| # Main Loop of the performance baseline testing #
 | |
| #################################################
 | |
| version=`lsxcatd -a 2>/dev/null | grep Version`
 | |
| if [ 0 != $? ]; then
 | |
|     echo "ERROR: xCAT daemon is not running. Start 'xcatd' and rerun this tool."
 | |
|     exit 99
 | |
| fi
 | |
| 
 | |
| mkdir -p $PERFORMANCE_DIR
 | |
| 
 | |
| lsdef -t node --template $PERF_NODETEMPL > $PERFORMANCE_NODE_TMPL 2>/dev/null
 | |
| if [ 0 != $? ]; then
 | |
|     echo "ERROR: Cannot find the default template for `arch`, make sure it exists and rerun this tool."
 | |
|     exit 99
 | |
| fi
 | |
| #Get available OS image, it will be used for nodeset if possible
 | |
| osimage=$(getOSimage)
 | |
| 
 | |
| rack=$(expr $FAKE_NODE_TOTAL / $NODE_PER_ROW)
 | |
| 
 | |
| echo "=================================================="
 | |
| # Starting to add fake nodes
 | |
| starttime=`date +'%Y-%m-%d %H:%M:%S'`
 | |
| start=$(getTime "$starttime")
 | |
| bootstrap 50
 | |
| endtime=`date +'%Y-%m-%d %H:%M:%S'`
 | |
| end=$(getTime "$endtime")
 | |
| echo
 | |
| echo "=================================================="
 | |
| 
 | |
| #echo "It takes $(($end-$start)) seconds to create $FAKE_NODE_TOTAL nodes"
 | |
| #echo "$FAKE_NODE_TOTAL", "$(($end-$start))", "mkdef" >> $PERFORMANCE_REPORT
 | |
| 
 | |
| if [ -z $RUN_CMD_LIST ]; then
 | |
|   echo "Done. Check the stanz file in $PERFORMANCE_STANZ"
 | |
|   exit 0
 | |
| fi
 | |
| 
 | |
| echo "Continue the performance testing for commands in $RUN_CMD_LIST "
 | |
| if [ -z "$osimage" ]; then
 | |
|   echo "WARN: Cannot determine the OS image, the commands which defined with #OSIMAGE# will be failed."
 | |
| fi
 | |
| 
 | |
| echo $version | tee $PERFORMANCE_REPORT
 | |
| echo "=================================================="
 | |
| 
 | |
| # Initial Populate the fake nodes into DB
 | |
| if [ -z $PERF_NOCREATE ]; then
 | |
|   #create fake network for makedns, makedhcp etc...
 | |
|   fakeNetwork
 | |
|   execCmd "mkdef -z -f < $PERFORMANCE_STANZ" "$FAKE_NODE_TOTAL"
 | |
| fi
 | |
| 
 | |
| # fake interface is required for topology with service nodes as it will determine if then Mn/Sn are
 | |
| # in the same subnet with CNs
 | |
| fakeInterface $FAKE_NETWORK_INTF
 | |
| 
 | |
| series=`grep '^#SERIES#' $RUN_CMD_LIST | awk  '{print $2}'`
 | |
| if [ ! -z $series ]; then
 | |
|   series=${series//,/ }
 | |
| fi
 | |
| #echo $series
 | |
| 
 | |
| cmdlist=`cat $RUN_CMD_LIST`
 | |
| IFS_BAK=$IFS
 | |
| IFS=$'\n'
 | |
| for line in $cmdlist
 | |
| do
 | |
|   [ "x${line:0:1}" = "x#" ] && continue
 | |
| 
 | |
|   # begin to run the command
 | |
|   IFS=$IFS_BAK
 | |
|   runTest "$line" "$series"
 | |
|   IFS=$'\n'
 | |
| done
 | |
| IFS=$IFS_BAK
 | |
| IFS_BAK=
 | |
| 
 | |
| rm -f $PERFORMANCE_NODE_TMPL
 | |
| rm -f $PERFORMANCE_STANZ
 | |
| fakeInterface $FAKE_NETWORK_INTF del
 | |
| 
 | |
| if [ -z $PERF_DRYRUN ]; then
 | |
|   echo
 | |
|   echo "Done. Check the performance result in $PERFORMANCE_REPORT"
 | |
| fi
 |