I created a little script to keep track of the disk states (spindown/spinup) using collectd, InfluxDB and Grafana.
It is based on this script: https://github.com/collectd/co…ter/contrib/exec-smartctl
Now I can see in a nice graphic about which drive was spun up or down at wich point.
Requirements:
- collectd (to collect the data; is already part of OMV)
- InfluxDB (to store the data)
- Grafana (to show the data)
I will not explain how to install InfluxDB and Grafana. There are plenty of tutorials available.
First, you need to configure collectd to send the data to InfluxDB.
Create the following file to configure collectd to send data to your InfluxDB-Server.
Don't forget to change the ip address.
#!/bin/sh
# This script adds support for sending data to InfluxDB
set -e
. /etc/default/openmediavault
. /usr/share/openmediavault/scripts/helper-functions
OMV_COLLECTD_CONFIG=${OMV_COLLECTD_CONFIG:-"/etc/collectd/collectd.conf"}
OMV_COLLECTD_RRDTOOL_MKGRAPH=${OMV_COLLECTD_RRDTOOL_MKGRAPH:-"/usr/sbin/omv-mkgraph"}
HOST_NAME=`hostname`
# change hostname
sed -i -e "s/Hostname\ \"localhost\"/Hostname\ \"$HOST_NAME\"/g" ${OMV_COLLECTD_CONFIG}
cat <<EOF >> ${OMV_COLLECTD_CONFIG}
LoadPlugin network
<Plugin "network">
Server "<<<<influxdb-ip-address>>>" "25826"
</Plugin>
EOF
Alles anzeigen
EDIT: I think I forgot to mention you need to copy https://github.com/collectd/co…/blob/master/src/types.db to /usr/share/collectd/types.db.
And also see this guide to prepare InfluxDB to receive data from collectd. https://anomaly.io/collectd-metrics-to-influxdb/
Create a user named 'smart' that has the permission to execute 'smartctl' with sudo.
Cmnd_Alias SMARTCTL = /usr/sbin/smartctl
smart ALL = (root) NOPASSWD: SMARTCTL
Create the following file which will read the power state of your drives.
Change the list of drives ("[..] sda sdb sdc ...") according to your system.
#!/bin/bash
HOSTNAME="${COLLECTD_HOSTNAME:-$(hostname -f)}"
INTERVAL="${COLLECTD_INTERVAL:-60}"
# ls /dev | grep -E "^sd[a-z]$"
while sleep "$INTERVAL"
do
for disk in sda sdb sdc sdd sde sdf
do
STATE=$(sudo smartctl -i -n standby /dev/$disk | grep -e "Device is in STANDBY mode" -e "Power mode is: ACTIVE or IDLE" 2>/dev/null)
if [ "$STATE" = "Device is in STANDBY mode, exit(2)" ]
then
# STANBY
VALUE="0"
else
if [ "$STATE" = "Power mode is: ACTIVE or IDLE" ]
then
# ACTIVE or IDLE
VALUE="1"
else
# ERROR
VALUE="U"
fi
fi
echo "PUTVAL $HOSTNAME/exec-$disk/gauge-disk_state interval=$INTERVAL N:$VALUE"
done
done
Alles anzeigen
If you execute the script manually it will take 60 seconds before the first output is printed.
As a bonus, here is the slightly modified version of the original exec-smartctl script.
This will read the disk temperature only when the disks are not in standby.
#!/bin/bash
HOSTNAME="${COLLECTD_HOSTNAME:-$(hostname -f)}"
INTERVAL="${COLLECTD_INTERVAL:-10}"
while sleep "$INTERVAL"
do
for disk in sda sdb sdc sdd sde sdf
do
TEMP=$((sudo smartctl -n standby -d ata -A /dev/$disk | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null);
if [ $? -ne 0 ]
then
TEMP="U"
fi
echo "PUTVAL $HOSTNAME/exec-$disk/temperature-disk_temp interval=$INTERVAL N:$TEMP"
done
done
Alles anzeigen
Don't forget to make the scripts executable.
Now we need to tell collectd to use these scripts.
#!/bin/sh
# This script adds support for hdd power state
set -e
. /etc/default/openmediavault
. /usr/share/openmediavault/scripts/helper-functions
OMV_COLLECTD_CONFIG=${OMV_COLLECTD_CONFIG:-"/etc/collectd/collectd.conf"}
OMV_COLLECTD_RRDTOOL_MKGRAPH=${OMV_COLLECTD_RRDTOOL_MKGRAPH:-"/usr/sbin/omv-mkgraph"}
cat <<EOF >> ${OMV_COLLECTD_CONFIG}
LoadPlugin exec
<Plugin exec>
Exec "smart" "/usr/share/collectd/exec-disk_state.sh"
Exec "smart" "/usr/share/collectd/exec-smartctl"
</Plugin>
EOF
Alles anzeigen
Finally execute the following commands to create and activate the new collectd config.
# create config
sudo omv-mkconf collectd
# Restart collectd (not sure if necessary)
sudo systemctl restart collectd.service
At this moment the data should be sent to your InfluxDB.
The next step is to create a nice graph for this data.
To display the graph with discrete values install this plugin: https://grafana.com/plugins/natel-discrete-panel
I used this dashboard template as a starting point: https://grafana.com/dashboards/554
You can import my graphs using this json data.
{
"backgroundColor": "rgba(128, 128, 128, 0.1)",
"colorMaps": [
{
"color": "rgb(148, 45, 45)",
"text": "active"
},
{
"color": "rgb(94, 159, 61)",
"text": "standby"
}
],
"datasource": "$datasource",
"display": "timeline",
"extendLastValue": true,
"height": "",
"highlightOnMouseover": true,
"id": 17,
"legendSortBy": "-ms",
"lineColor": "rgba(128, 128, 128, 1.0)",
"links": [],
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"metricNameColor": "#000000",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"rowHeight": 16,
"showDistinctCount": false,
"showLegend": true,
"showLegendCounts": false,
"showLegendNames": true,
"showLegendPercent": false,
"showLegendTime": true,
"showLegendValues": true,
"showTransitionCount": false,
"span": 6,
"targets": [
{
"alias": "$tag_instance",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"instance"
],
"type": "tag"
}
],
"hide": false,
"measurement": "exec_value",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
}
]
],
"tags": [
{
"key": "host",
"operator": "=~",
"value": "/^$host$/"
},
{
"condition": "AND",
"key": "type_instance",
"operator": "=",
"value": "disk_state"
}
]
}
],
"textSize": 12,
"title": "Disk states",
"type": "natel-discrete-panel",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
},
{
"op": "=",
"text": "standby",
"value": "0"
},
{
"op": "=",
"text": "active",
"value": "1"
}
],
"valueTextColor": "#000000",
"writeAllValues": false,
"writeLastValue": true,
"writeMetricNames": true
}
Alles anzeigen
{
"backgroundColor": "rgba(128, 128, 128, 0.1)",
"colorMaps": [
{
"color": "rgb(148, 45, 45)",
"text": "active"
},
{
"color": "rgb(94, 159, 61)",
"text": "standby"
}
],
"datasource": "$datasource",
"display": "timeline",
"extendLastValue": true,
"height": "",
"highlightOnMouseover": true,
"id": 17,
"legendSortBy": "-ms",
"lineColor": "rgba(128, 128, 128, 1.0)",
"links": [],
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"metricNameColor": "#000000",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"rowHeight": 16,
"showDistinctCount": false,
"showLegend": true,
"showLegendCounts": false,
"showLegendNames": true,
"showLegendPercent": false,
"showLegendTime": true,
"showLegendValues": true,
"showTransitionCount": false,
"span": 6,
"targets": [
{
"alias": "$tag_instance",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"instance"
],
"type": "tag"
}
],
"hide": false,
"measurement": "exec_value",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"value"
],
"type": "field"
}
]
],
"tags": [
{
"key": "host",
"operator": "=~",
"value": "/^$host$/"
},
{
"condition": "AND",
"key": "type_instance",
"operator": "=",
"value": "disk_state"
}
]
}
],
"textSize": 12,
"title": "Disk states",
"type": "natel-discrete-panel",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
},
{
"op": "=",
"text": "standby",
"value": "0"
},
{
"op": "=",
"text": "active",
"value": "1"
}
],
"valueTextColor": "#000000",
"writeAllValues": false,
"writeLastValue": true,
"writeMetricNames": true
}
Alles anzeigen
Or create the graphs manually according to this screenshots.
I hope this will be of use for someone.
And feel free to give feedback in any way.