upstream/openstack/python-heat/python-heat/templates/hot/demo/get_cpu_load

205 lines
6.0 KiB
Bash

#!/bin/bash
###############################################################################
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
###############################################################################
#
# Description:
# This displays total CPU occupancy based on hi-resolution timings.
#
###############################################################################
# Define minimal path
PATH=/bin:/usr/bin:/usr/local/bin
# NOTE: Comment out LOG_DEBUG and DEBUG_METHODS in production version.
# Uncomment LOG_DEBUG to enable debug print statements
##LOG_DEBUG=1
# Uncomment DEBUG_METHODS to enable test of methods
##DEBUG_METHODS=1
SCHEDSTAT_VERSION=$(cat /proc/schedstat 2>/dev/null | awk '/version/ {print $2;}')
NPROCESSORS_ONLN=$(getconf _NPROCESSORS_ONLN)
ARCH=$(arch)
# NOTE: we only support 64-bit math due to long integers of schedstat
SUPPORTED_SCHEDSTAT_VERSION=15
SUPPORTED_ARCH='x86_64'
# Customize sleep interval based on how responsive we want scaling to react.
# This is set small for demonstration purposes.
SLEEP_INTERVAL="1.0s"
# Log if debug is enabled via LOG_DEBUG
function log_debug
{
if [ ! -z "${LOG_DEBUG}" ]; then
logger -p debug -t "$0[${PPID}]" -s "$@" 2>&1
fi
}
# Log unconditionally to STDERR
function log_error
{
logger -p error -t "$0[${PPID}]" -s "$@"
}
# Log unconditionally to STDOUT
function log
{
logger -p info -t "$0[${PPID}]" -s "$@" 2>&1
}
function read_proc_schedstat
{
local _outvar=$1
local _result # Use some naming convention to avoid OUTVARs to clash
local _cpu
local _cputime
_result=0
while read -r line
do
# version 15: cputime is 7th field
if [[ $line =~ ^cpu([[:digit:]]+)[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+([[:digit:]]+)[[:space:]]+ ]]
then
_cpu=${BASH_REMATCH[1]}
_cputime=${BASH_REMATCH[2]}
((_result += _cputime))
fi
done < "/proc/schedstat"
eval $_outvar=\$_result # Instead of just =$_result
}
function occupancy_loadavg()
{
# NOTE: This method is not recommended, as the feedback is slow and
# based on the loadavg 1-minute decay. The loadavg also includes
# IoWait which isn't desired. This does not require large integers.
# Calculate total CPU occupancy based on 1 minute loadavg.
ldavg_1m=$(cat /proc/loadavg 2>/dev/null | awk '{print $1}')
# Calculate total CPU occupancy (%)
occ=$(awk -v ldavg=${ldavg_1m} -v N=${NPROCESSORS_ONLN} \
'BEGIN {printf "%.1f\n", 100.0 * ldavg / N;}'
)
log_debug "CPU Occupancy(loadavg): ${occ}"
echo ${occ}
}
function occupancy_jiffie()
{
# NOTE: This method is not recommended, as the per-cpu stats are not
# properly updated by the kernel after scaling VM back up.
# This routine uses simple small integer math.
# Calculate total CPU occupancy based on jiffie stats.
read cpu user nice system idle iowait irq softirq steal guest < /proc/stat
j_occ_0=$((user+system+nice+irq+softirq+steal))
j_tot_0=$((user+system+nice+irq+softirq+steal+idle+iowait))
sleep ${SLEEP_INTERVAL}
read cpu user nice system idle iowait irq softirq steal guest < /proc/stat
j_occ_1=$((user+system+nice+irq+softirq+steal))
j_tot_1=$((user+system+nice+irq+softirq+steal+idle+iowait))
# Calculate total CPU occupancy (%)
occ=$(( 100 * (j_occ_1 - j_occ_0) / (j_tot_1 - j_tot_0) ))
log_debug "CPU Occupancy(jiffie): ${occ}"
echo ${occ}
}
function occupancy_schedstat()
{
# NOTE: This method is recommended as timings are high resolution.
# However the timings require large integers, so we are assuming
# we require 64-bit guest.
# Calculate total CPU occupancy based on uptime stats
local cputime_0=''
local cputime_1=''
read t_elapsed_0 t_idle_0 < /proc/uptime
read_proc_schedstat cputime_0
sleep ${SLEEP_INTERVAL}
read t_elapsed_1 t_idle_1 < /proc/uptime
read_proc_schedstat cputime_1
# Calculate total CPU occupancy (%)
occ=$(awk -v te0=${t_elapsed_0} -v te1=${t_elapsed_1} \
-v tc0=${cputime_0} -v tc1=${cputime_1} \
-v N=${NPROCESSORS_ONLN} \
'BEGIN {dt_ms = N*(te1 - te0)*1E3; cputime_ms = (tc1 - tc0)/1.0E6;
occ = 100.0 * cputime_ms / dt_ms;
printf "%.1f\n", occ;}'
)
log_debug "CPU Occupancy(schedstat): ${occ}"
echo ${occ}
}
function occupancy_uptime()
{
# NOTE: This method is is very similar to the loadavg method in that
# IoWait is treated as load, but the occupancy is instantaneous.
# This does not require large integers.
# Calculate total CPU occupancy based on uptime/idle stats
read t_elapsed_0 t_idle_0 < /proc/uptime
sleep ${SLEEP_INTERVAL}
read t_elapsed_1 t_idle_1 < /proc/uptime
# Calculate total CPU occupancy (%)
occ=$(awk -v te0=${t_elapsed_0} -v ti0=${t_idle_0} \
-v te1=${t_elapsed_1} -v ti1=${t_idle_1} \
-v N=${NPROCESSORS_ONLN} \
'BEGIN {dt = N*(te1 - te0); di = ti1 - ti0; cputime = dt - di;
occ = 100.0 * cputime / dt;
printf "%.1f\n", occ;}'
)
log_debug "CPU Occupancy(uptime): ${occ}"
echo ${occ}
}
###############################################################################
#
# MAIN Program
#
###############################################################################
if [ ! -z "${DEBUG_METHODS}" ]
then
log_debug "Testing occupancy_loadavg"
occupancy_loadavg
log_debug "Testing occupancy_jiffie"
occupancy_jiffie
log_debug "Testing occupancy_uptime"
occupancy_uptime
log_debug "Testing occupancy_schedstat"
occupancy_schedstat
fi
log_debug "Discovered arch=${ARCH}, schedstat version=${SCHEDSTAT_VERSION}."
if [[ ${ARCH} == ${SUPPORTED_ARCH} ]] && [[ ${SCHEDSTAT_VERSION} -eq ${SUPPORTED_SCHEDSTAT_VERSION} ]]
then
occupancy_schedstat
else
occupancy_uptime
fi
exit 0