| #!/bin/bash | |
| # | |
| # | |
| # SysInfo OCF Resource Agent | |
| # It records (in the CIB) various attributes of a node | |
| # | |
| # Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Brée | |
| # All Rights Reserved. | |
| # | |
| # This program is free software; you can redistribute it and/or modify | |
| # it under the terms of version 2 of the GNU General Public License as | |
| # published by the Free Software Foundation. | |
| # | |
| # This program is distributed in the hope that it would be useful, but | |
| # WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| # | |
| # Further, this software is distributed without any warranty that it is | |
| # free of the rightful claim of any third person regarding infringement | |
| # or the like. Any license provided herein, whether implied or | |
| # otherwise, applies only to this software file. Patent licenses, if | |
| # any, provided herein do not apply to combinations of this program with | |
| # other software, or any other product whatsoever. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program; if not, write the Free Software Foundation, | |
| # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
| # | |
| ####################################################################### | |
| # Initialization: | |
| : ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs} | |
| . ${OCF_FUNCTIONS} | |
| : ${__OCF_ACTION=$1} | |
| ####################################################################### | |
| meta_data() { | |
| cat <<END | |
| <?xml version="1.0"?> | |
| <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd"> | |
| <resource-agent name="SysInfo" version="1.0"> | |
| <version>1.0</version> | |
| <longdesc lang="en"> | |
| This is a SysInfo Resource Agent. | |
| It records (in the CIB) various attributes of a node | |
| Sample Linux output: | |
| arch: i686 | |
| os: Linux-2.4.26-gentoo-r14 | |
| free_swap: 1999 | |
| cpu_info: Intel(R) Celeron(R) CPU 2.40GHz | |
| cpu_speed: 4771.02 | |
| cpu_cores: 1 | |
| cpu_load: 0.00 | |
| ram_total: 513 | |
| ram_free: 117 | |
| root_free: 2.4 | |
| #health_disk: red | |
| Sample Darwin output: | |
| arch: i386 | |
| os: Darwin-8.6.2 | |
| cpu_info: Intel Core Duo | |
| cpu_speed: 2.16 | |
| cpu_cores: 2 | |
| cpu_load: 0.18 | |
| ram_total: 2016 | |
| ram_free: 787 | |
| root_free: 13 | |
| #health_disk: green | |
| Units: | |
| free_swap: MB | |
| ram_*: MB | |
| cpu_speed (Linux): bogomips | |
| cpu_speed (Darwin): GHz | |
| *_free: GB (or user-defined: disk_unit) | |
| </longdesc> | |
| <shortdesc lang="en">SysInfo resource agent</shortdesc> | |
| <parameters> | |
| <parameter name="pidfile" unique="1"> | |
| <longdesc lang="en">PID file</longdesc> | |
| <shortdesc lang="en">PID file</shortdesc> | |
| <content type="string" default="$OCF_RESKEY_pidfile" /> | |
| </parameter> | |
| <parameter name="delay" unique="0"> | |
| <longdesc lang="en">Interval to allow values to stabilize</longdesc> | |
| <shortdesc lang="en">Dampening Delay</shortdesc> | |
| <content type="string" default="0s" /> | |
| </parameter> | |
| <parameter name="disks" unique="0"> | |
| <longdesc lang="en"> | |
| Filesystems or Paths to be queried for free disk space as a SPACE | |
| separated list - e.g "/dev/sda1 /tmp". | |
| Results will be written to an attribute with leading slashes | |
| removed, and other slashes replaced with underscore, and the word | |
| 'free' appended - e.g for /dev/sda1 it would be 'dev_sda1_free'. | |
| Note: The root filesystem '/' is always queried to an attribute | |
| named 'root_free' | |
| </longdesc> | |
| <shortdesc lang="en">List of Filesytems/Paths to query for free disk space</shortdesc> | |
| <content type="string" /> | |
| </parameter> | |
| <parameter name="disk_unit" unique="0"> | |
| <longdesc lang="en"> | |
| Unit to report disk free space in. | |
| Can be one of: B, K, M, G, T, P (case-insensitive) | |
| </longdesc> | |
| <shortdesc lang="en">Unit to report disk free space in</shortdesc> | |
| <content type="string" default="G"/> | |
| </parameter> | |
| <parameter name="min_disk_free" unique="0"> | |
| <longdesc lang="en"> | |
| The amount of free space required in monitored disks. If any | |
| of the monitored disks has less than this amount of free space, | |
| , with the node attribute "#health_disk" changing to "red", | |
| all resources will move away from the node. Set the node-health-strategy | |
| property appropriately for this to take effect. | |
| If the unit is not specified, it defaults to disk_unit. | |
| </longdesc> | |
| <shortdesc lang="en">minimum disk free space required</shortdesc> | |
| <content type="string" default=""/> | |
| </parameter> | |
| </parameters> | |
| <actions> | |
| <action name="start" timeout="20s" /> | |
| <action name="stop" timeout="20s" /> | |
| <action name="monitor" timeout="20s" interval="60s"/> | |
| <action name="meta-data" timeout="5" /> | |
| <action name="validate-all" timeout="30" /> | |
| </actions> | |
| </resource-agent> | |
| END | |
| } | |
| ####################################################################### | |
| UpdateStat() { | |
| name=$1; shift | |
| value="$*" | |
| printf "%s:\t%s\n" "$name" "$value" | |
| if [ "$__OCF_ACTION" = "start" ] ; then | |
| ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n $name -B "$value" | |
| else | |
| ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n $name -v "$value" | |
| fi | |
| } | |
| SysInfoStats() { | |
| local DISK_STATUS="green" | |
| UpdateStat arch "`uname -m`" | |
| UpdateStat os "`uname -s`-`uname -r`" | |
| case `uname -s` in | |
| "Darwin") | |
| mem=`top -l 1 | grep Mem: | awk '{print $10}'` | |
| mem_used=`top -l 1 | grep Mem: | awk '{print $8}'` | |
| mem=`SysInfo_mem_units $mem` | |
| mem_used=`SysInfo_mem_units $mem_used` | |
| mem_total=`expr $mem_used + $mem` | |
| cpu_type=`system_profiler SPHardwareDataType | awk -F': ' '/^CPU Type/ {print $2; exit}'` | |
| cpu_speed=`system_profiler SPHardwareDataType | awk -F': ' '/^CPU Speed/ {print $2; exit}'` | |
| cpu_cores=`system_profiler SPHardwareDataType | awk -F': ' '/^Number Of/ {print $2; exit}'` | |
| cpu_load=`uptime | awk '{ print $10 }'` | |
| ;; | |
| "FreeBSD") | |
| cpu_type=`sysctl -in hw.model` | |
| cpu_speed=`sysctl -in dev.cpu.0.freq` | |
| cpu_cores=`sysctl -in hw.ncpu` | |
| cpu_load=`sysctl -in vm.loadavg | awk '{ print $4 }'` | |
| free_pages=`sysctl -in vm.stats.vm.v_free_count` | |
| page_count=`sysctl -in vm.stats.vm.v_page_count` | |
| page_size=`sysctl -in vm.stats.vm.v_page_size` | |
| mem=`expr $free_pages \* $page_size / 1024 / 1024`M | |
| mem_total=`expr $page_count \* $page_size / 1024 / 1024`M | |
| ;; | |
| "Linux") | |
| if [ -f /proc/cpuinfo ]; then | |
| cpu_type=`awk -F': ' '/model name/ {print $2; exit}' /proc/cpuinfo` | |
| cpu_speed=`awk -F': ' '/bogomips/ {print $2; exit}' /proc/cpuinfo` | |
| cpu_cores=`grep "^processor" /proc/cpuinfo | wc -l` | |
| fi | |
| cpu_load=`uptime | awk '{ print $10 }'` | |
| if [ -f /proc/meminfo ]; then | |
| # meminfo results are in kB | |
| mem=`grep "SwapFree" /proc/meminfo | awk '{print $2"k"}'` | |
| if [ ! -z $mem ]; then | |
| UpdateStat free_swap `SysInfo_mem_units $mem` | |
| fi | |
| mem=`grep "Inactive" /proc/meminfo | awk '{print $2"k"}'` | |
| mem_total=`grep "MemTotal" /proc/meminfo | awk '{print $2"k"}'` | |
| else | |
| mem=`top -n 1 | grep Mem: | awk '{print $7}'` | |
| fi | |
| ;; | |
| *) | |
| esac | |
| if [ x != x"$cpu_type" ]; then | |
| UpdateStat cpu_info "$cpu_type" | |
| fi | |
| if [ x != x"$cpu_speed" ]; then | |
| UpdateStat cpu_speed "$cpu_speed" | |
| fi | |
| if [ x != x"$cpu_cores" ]; then | |
| UpdateStat cpu_cores "$cpu_cores" | |
| fi | |
| if [ x != x"$cpu_load" ]; then | |
| UpdateStat cpu_load "$cpu_load" | |
| fi | |
| if [ ! -z "$mem" ]; then | |
| # Massage the memory values | |
| UpdateStat ram_total `SysInfo_mem_units $mem_total` | |
| UpdateStat ram_free `SysInfo_mem_units $mem` | |
| fi | |
| # Portability notes: | |
| # o tail: explicit "-n" not available in Solaris; instead simplify | |
| # 'tail -n <c>' to the equivalent 'tail -<c>'. | |
| for disk in "/" ${OCF_RESKEY_disks}; do | |
| unset disk_free disk_label | |
| disk_free=`df -h ${disk} | tail -1 | awk '{print $4}'` | |
| if [ x != x"$disk_free" ]; then | |
| disk_label=`echo $disk | sed -e 's#^/$#root#;s#^/*##;s#/#_#g'` | |
| disk_free=`SysInfo_hdd_units $disk_free` | |
| UpdateStat ${disk_label}_free $disk_free | |
| if [ -n "$MIN_FREE" ] && [ $disk_free -le $MIN_FREE ]; then | |
| DISK_STATUS="red" | |
| fi | |
| fi | |
| done | |
| UpdateStat "#health_disk" "$DISK_STATUS" | |
| } | |
| SysInfo_megabytes() { | |
| # Size in megabytes | |
| echo $1 | awk '{ n = $0; | |
| sub(/[0-9]+(.[0-9]+)?/, ""); | |
| split(n, a, $0); | |
| n=a[1]; | |
| if ($0 == "G" || $0 == "") { n *= 1024 }; | |
| if (/^kB?/) { n /= 1024 }; | |
| printf "%d\n", n }' # Intentionally round to an integer | |
| } | |
| SysInfo_mem_units() { | |
| mem=$1 | |
| if [ -z $1 ]; then | |
| return | |
| fi | |
| mem=$(SysInfo_megabytes "$1") | |
| # Round to the next multiple of 50 | |
| r=$(($mem % 50)) | |
| if [ $r != 0 ]; then | |
| mem=$(($mem + 50 - $r)) | |
| fi | |
| echo $mem | |
| } | |
| SysInfo_hdd_units() { | |
| # Defauts to size in gigabytes | |
| case $OCF_RESKEY_disk_unit in | |
| [Pp]) echo $(($(SysInfo_megabytes "$1") / 1024 / 1024 / 1024));; | |
| [Tt]) echo $(($(SysInfo_megabytes "$1") / 1024 / 1024));; | |
| [Gg]) echo $(($(SysInfo_megabytes "$1") / 1024));; | |
| [Mm]) echo $(SysInfo_megabytes "$1");; | |
| [Kk]) echo $(($(SysInfo_megabytes "$1") * 1024));; | |
| [Bb]) echo $(($(SysInfo_megabytes "$1") * 1024 * 1024));; | |
| *) | |
| ocf_log err "Invalid value for disk_unit: $OCF_RESKEY_disk_unit" | |
| echo $(($(SysInfo_megabytes "$1") / 1024));; | |
| esac | |
| } | |
| SysInfo_usage() { | |
| cat <<END | |
| usage: $0 {start|stop|monitor|validate-all|meta-data} | |
| Expects to have a fully populated OCF RA-compliant environment set. | |
| END | |
| } | |
| SysInfo_start() { | |
| echo $OCF_RESKEY_clone > $OCF_RESKEY_pidfile | |
| SysInfoStats | |
| exit $OCF_SUCCESS | |
| } | |
| SysInfo_stop() { | |
| rm $OCF_RESKEY_pidfile | |
| exit $OCF_SUCCESS | |
| } | |
| SysInfo_monitor() { | |
| if [ -f $OCF_RESKEY_pidfile ]; then | |
| clone=`cat $OCF_RESKEY_pidfile` | |
| fi | |
| if [ x$clone = x ]; then | |
| rm $OCF_RESKEY_pidfile | |
| exit $OCF_NOT_RUNNING | |
| elif [ $clone = $OCF_RESKEY_clone ]; then | |
| SysInfoStats | |
| exit $OCF_SUCCESS | |
| elif [ x$OCF_RESKEY_CRM_meta_globally_unique = xtrue | |
| -o x$OCF_RESKEY_CRM_meta_globally_unique = xTrue | |
| -o x$OCF_RESKEY_CRM_meta_globally_unique = xyes | |
| -o x$OCF_RESKEY_CRM_meta_globally_unique = xYes | |
| ]; then | |
| SysInfoStats | |
| exit $OCF_SUCCESS | |
| fi | |
| exit $OCF_NOT_RUNNING | |
| } | |
| SysInfo_validate() { | |
| return $OCF_SUCCESS | |
| } | |
| if [ $# -ne 1 ]; then | |
| SysInfo_usage | |
| exit $OCF_ERR_ARGS | |
| fi | |
| : ${OCF_RESKEY_pidfile:="${HA_VARRUN%%/}/SysInfo-${OCF_RESOURCE_INSTANCE}"} | |
| : ${OCF_RESKEY_disk_unit:="G"} | |
| : ${OCF_RESKEY_clone:="0"} | |
| if [ x != x${OCF_RESKEY_delay} ]; then | |
| OCF_RESKEY_delay="-d ${OCF_RESKEY_delay}" | |
| else | |
| OCF_RESKEY_delay="-d 0" | |
| fi | |
| MIN_FREE="" | |
| if [ -n "$OCF_RESKEY_min_disk_free" ]; then | |
| ocf_is_decimal "$OCF_RESKEY_min_disk_free" && | |
| OCF_RESKEY_min_disk_free="$OCF_RESKEY_min_disk_free$OCF_RESKEY_disk_unit" | |
| MIN_FREE=`SysInfo_hdd_units $OCF_RESKEY_min_disk_free` | |
| fi | |
| case $__OCF_ACTION in | |
| meta-data) meta_data | |
| exit $OCF_SUCCESS | |
| ;; | |
| start) SysInfo_start | |
| ;; | |
| stop) SysInfo_stop | |
| ;; | |
| monitor) SysInfo_monitor | |
| ;; | |
| validate-all) SysInfo_validate | |
| ;; | |
| usage|help) SysInfo_usage | |
| exit $OCF_SUCCESS | |
| ;; | |
| *) SysInfo_usage | |
| exit $OCF_ERR_UNIMPLEMENTED | |
| ;; | |
| esac | |
| exit $? |