diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMI.page b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMI.page new file mode 100644 index 00000000..cfa22de1 --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMI.page @@ -0,0 +1,6 @@ +Menu="NetworkServices" +Icon="ipmitool.png" +Title="IPMI tool" +Type="xmenu" +Tabs="true" +--- diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIButton.page b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIButton.page new file mode 100644 index 00000000..ef3358b8 --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIButton.page @@ -0,0 +1,28 @@ +Menu="Buttons:2" +Link="nav-user" +--- + + + \ No newline at end of file diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIEvents.page b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIEvents.page index ea0de7f4..05dd959b 100644 --- a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIEvents.page +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIEvents.page @@ -6,7 +6,7 @@ Title="Event Log" Status - Event ID + Event ID Time Stamp Sensor Name Description diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIFans.page b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIFans.page new file mode 100644 index 00000000..e164aba5 --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMIFans.page @@ -0,0 +1,113 @@ +Menu="IPMI:2" +Title="Fan Control" +--- + +$name, 'name'=>end(split('/',$pwm)), 'sensor'=>$pwm); + } + } + return $out; +} +?> + + +
+ + + + + +Fan control function: +: + +PWM controller: +: + +PWM fan: +: + +Minimun PWM value: +: + +Low temperature threshold (°): +: + +High temperature threshold (°): +: + +Refresh interval (minutes): +: + + +: +
diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISensors.page b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISensors.page index 6d8c6048..41ea2f66 100644 --- a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISensors.page +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISensors.page @@ -1,20 +1,10 @@ Menu="IPMItool:1" Title="Sensors" +Icon="sensorspage.png" --- - - - +.css">
@@ -44,8 +34,3 @@ $theme = $display["theme"]; - - diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISettings.page b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISettings.page index 8e6c4248..1fc465c7 100644 --- a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISettings.page +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/IPMISettings.page @@ -1,17 +1,9 @@ -Icon="ipmitool.png" -Menu="NetworkServices" -Title="IPMI tool" +Menu="IPMI:1" +Title="Settings" --- /dev/null`/exe ] && echo 'yes' || echo 'no' 2> /dev/null" )); ?> @@ -27,21 +19,36 @@ Enable Event Notifications: Enable Remote Connection: -: - -: + +: - -: + +: - -: + +: - +Display CPU temperature: +: + +Display Motherboard temperature: +: + +Display Fan speed: +: + + : @@ -52,7 +59,7 @@ $(function(){ checkREMOTE(document.ipmitool_settings); decData(document.ipmitool_settings); //ip address input mask - $('.ipmi_address').mask('0ZZ.0ZZ.0ZZ.0ZZ', {translation: {'Z': {pattern: /[0-9]/, optional: true}}}); + $('.ipmitool-ipaddr').mask('0ZZ.0ZZ.0ZZ.0ZZ', {translation: {'Z': {pattern: /[0-9]/, optional: true}}}); }); function resetDATA(form) { @@ -66,10 +73,10 @@ function resetDATA(form) { function checkRUNNING(form) { if ("" == "yes") { - $(".ipmi_run").prop("disabled", true); + $(".ipmitool-run").prop("disabled", true); form.btnApply.disabled = "disabled"; }else{ - $(".ipmi_run").prop("disabled", false); + $(".ipmitool-run").prop("disabled", false); $("#btnApply").prop("disabled", false); } if (form.SERVICE.value == "enable") @@ -85,10 +92,10 @@ function decData(form) { function checkREMOTE(form) { if (form.REMOTE.selectedIndex < 1 ) - $(".ipmi_lan").hide(); + $(".ipmitool-lan").hide(); else - $(".ipmi_lan").show(); - $(".ipmi_lan").prop("disabled", (form.SERVICE.value == "enable")); + $(".ipmitool-lan").show(); + $(".ipmitool-lan").prop("disabled", (form.SERVICE.value == "enable")); } function verifyDATA(form) { @@ -97,5 +104,4 @@ function verifyDATA(form) { form.USER.value = form.USER.value.replace(/ /g,"_"); form.PASSWORD.value = btoa(form.PASSWORD.value); } - diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/css/ipmitool-plugin.css b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/css/ipmitool-plugin.css index 645521f7..d42e48df 100644 --- a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/css/ipmitool-plugin.css +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/css/ipmitool-plugin.css @@ -1,5 +1,5 @@ /* header */ -table.tablesorter { +table.tablesorter{ margin-top:-21px; } .tablesorter td.reading{ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/cpu.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/cpu.png new file mode 100644 index 00000000..cec150b3 Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/cpu.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/fan.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/fan.png new file mode 100644 index 00000000..9a71d40a Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/fan.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/mb.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/mb.png new file mode 100644 index 00000000..ef76789f Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/mb.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/sensors2.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/sensors2.png new file mode 100644 index 00000000..69cc1e21 Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/sensors2.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/settings.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/settings.png new file mode 100644 index 00000000..715bef64 Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/settings.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/systemtemp.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/systemtemp.png new file mode 100644 index 00000000..9c506572 Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/icons/systemtemp.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/images/dynamix.system.temp.png b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/images/dynamix.system.temp.png new file mode 100644 index 00000000..3c051462 Binary files /dev/null and b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/images/dynamix.system.temp.png differ diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/delete_event.php b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/delete_event.php deleted file mode 100644 index 038d6b5c..00000000 --- a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/delete_event.php +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/fancontrol.php b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/fancontrol.php new file mode 100644 index 00000000..0135ef40 --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/fancontrol.php @@ -0,0 +1,248 @@ +#!/usr/bin/php +/dev/null", $crontab); + $crontab = array_unique($crontab); + if (! isset($quit)){ + $entry = sprintf("*/%s * * * * ${service_file}${background_args} 1> /dev/null 2>&1", $cron); + if (! preg_grep("#${service_file}#", $crontab)){ + $crontab[] = $entry; + debug("\nCRONTAB\n".implode("\n", $crontab)."\n"); + file_put_contents("/tmp/${program_name}.cron", implode(PHP_EOL, $crontab)); + shell_exec("crontab /tmp/${program_name}.cron"); + unlink("/tmp/$program_name.cron"); + } + } + unset($crontab); +} else if (isset($quit)){ + exec("crontab -l 2>/dev/null", $crontab); + $crontab = array_unique($crontab); + if (preg_grep("#${service_file}#", $crontab)){ + $crontab = preg_grep("#${service_file}#", $crontab, PREG_GREP_INVERT); + debug("\nCRONTAB\n".implode("\n", $crontab)."\n"); + file_put_contents("/tmp/${program_name}.cron", implode(PHP_EOL, $crontab)); + shell_exec("crontab /tmp/${program_name}.cron"); + unlink("/tmp/$program_name.cron"); + }; + unset($crontab); +} + +if (is_file($lockfile)){ + $lock_pid = file($lockfile, FILE_IGNORE_NEW_LINES)[0]; + $pid_running=preg_replace("/\s+/", "", shell_exec("ps -p ${lock_pid}| grep ${lock_pid}")); + if (! $pid_running){ + if (! isset($quit)){ + file_put_contents($lockfile, getmypid()); + } else { + echo "${lock_pid} is not currently running"; + unlink($lockfile); + exit(0); + } + } else { + if (isset($quit)){ + syslog(LOG_INFO, "killing daemon with PID [${lock_pid}]"); + exec("kill $lock_pid"); + unlink($lockfile); + if (function_exists('at_exit')) at_exit(); + exit(0); + } else { + echo "$program_name is already running [${lock_pid}]".PHP_EOL; + exit(0); + } + } +} else { + if(isset($quit)){ + echo "$program_name not currently running".PHP_EOL; + exit(0); + } else { + file_put_contents($lockfile, getmypid()); + } +} + +if(!isset($background)){ + exec("php $service_file --background $background_args 1>/dev/null ".($DEBUG ? "":"2>&1 ")."&"); + exit(0); +} else { + syslog(LOG_INFO, "process started. To terminate it, type: $program_name -q"); +} + +############################## +##### PROGRAM SECTION ###### +############################## +$plugin = "dynamix.system.autofan"; +$config_file = "/boot/config/plugins/${plugin}/fan.conf"; + +function scan_dir($dir, $type = ""){ + $out = array(); + foreach (array_slice(scandir($dir), 2) as $entry){ + $sep = (preg_match("/\/$/", $dir)) ? "" : "/"; + $out[] = $dir.$sep.$entry ; + } + return $out; +} + +function get_highest_temp($hdds){ + $highest_temp="0"; + foreach ($hdds as $hdd) { + if (shell_exec("hdparm -C ${hdd} 2>/dev/null| grep -c standby") == 0){ + $temp = preg_replace("/\s+/", "", shell_exec("smartctl -A ${hdd} 2>/dev/null| grep -m 1 -i Temperature_Celsius | awk '{print $10}'")); + $highest_temp = ($temp > $highest_temp) ? $temp : $highest_temp; + } + } + debug("Highest temp is ${highest_temp}ºC"); + return $highest_temp; +} + +function get_all_hdds(){ + $hdds = array(); + $flash = preg_replace("/\d$/", "", realpath("/dev/disk/by-label/UNRAID")); + foreach (scan_dir("/dev/") as $dev) { + if(preg_match("/[sh]d[a-z]+$/", $dev) && $dev != $flash) { + $hdds[] = $dev; + } + } + return $hdds; +} + +$hdds = get_all_hdds(); +while(TRUE){ while(TRUE){ +#### DO YOUR STUFF HERE #### + +# Load config file or die +if(is_file($config_file)){ + $params = (is_file($config_file)) ? parse_ini_file($config_file) : array(); + extract($params, EXTR_OVERWRITE); +} else { + unlink($lockfile); + exit(1); +} + +# Wait probes to become ready +if (! is_file($PWM_CONTROLLER) || ! is_file($PWM_FAN)){ + sleep(15); + continue; +} + +# Set PWM_HIGH and PWM_OFF +$PWM_HIGH = 255; +$PWM_OFF = $PWM_LOW-5; + +# Disable fan mininum RPM +$FAN_RPM_MIN = file(split("_", $PWM_FAN)[0]."_min", FILE_IGNORE_NEW_LINES)[0]; +$D_FAN_RPM_MIN = ($FAN_RPM_MIN > 0) ? $FAN_RPM_MIN : FALSE; + +# Enable speed change on fan +$PWM_MODE=file("${PWM_CONTROLLER}_enable", FILE_IGNORE_NEW_LINES)[0]; +if($PWM_MODE != 1){ + $DEFAULT_PWM_MODE = $PWM_MODE; + file_put_contents("${PWM_CONTROLLER}_enable", 1); +} + +# Calculate size of increments. +$TEMP_INCREMENTS = $TEMP_HIGH-$TEMP_LOW; +$PWM_INCREMENTS = round(($PWM_HIGH-$PWM_LOW)/$TEMP_INCREMENTS); +# Get current fan rpm and pwm +$CURRENT_PWM = preg_replace("/\s*/", "", file_get_contents($PWM_CONTROLLER)); +$CURRENT_RPM = preg_replace("/\s*/", "", file_get_contents($PWM_FAN)); +# Get current fan PWM percentage +$CURRENT_PERCENT_PWM = round(($CURRENT_PWM*100)/$PWM_HIGH); +$CURRENT_OUTPUT = "${CURRENT_PWM} (${CURRENT_PERCENT_PWM}% @ ${CURRENT_RPM}rpm)"; + +# Calculate a new scenario +# Get highest drive temperature +$HIGHEST_TEMP = get_highest_temp($hdds); +if ($HIGHEST_TEMP <= $TEMP_LOW){ + $NEW_PWM = $PWM_OFF; + $NEW_PERCENT_PWM = 0; +} else if ($HIGHEST_TEMP >= $TEMP_HIGH){ + $NEW_PWM = $PWM_HIGH; + $NEW_PERCENT_PWM = 100; +} else { + $NEW_PWM = (($HIGHEST_TEMP-$TEMP_LOW)*$PWM_INCREMENTS)+$PWM_LOW; + $NEW_PERCENT_PWM = round(($NEW_PWM*100)/$PWM_HIGH); +} + +# Change the fan speed as needed +if ($CURRENT_PWM != $NEW_PWM){ + file_put_contents($PWM_CONTROLLER, $NEW_PWM); + sleep(5); + $NEW_RPM = preg_replace("/\s*/", "", file_get_contents($PWM_FAN)); + $NEW_PERCENT_PWM = round(($NEW_PWM*100)/$PWM_HIGH); + $NEW_OUTPUT = "${NEW_PWM} (${NEW_PERCENT_PWM}% @ ${NEW_RPM}rpm)"; + syslog(LOG_INFO, "highest disk temp is ${HIGHEST_TEMP}ºC, adjusting fan PWM from: $CURRENT_OUTPUT to: $NEW_OUTPUT"); +} + +# PRINT VARIABLES DEBUG +$defined_vars = get_defined_vars(); +foreach (array("_GET","_POST","_COOKIE","_FILES","argv","argc","_SERVER") as $i) {unset($defined_vars[$i]);} +debug("\nDECLARED VARIABLES:\n".print_r($defined_vars, true)); +unset($defined_vars); + +$time1 = time(); +$MD5 = shell_exec("md5sum $config_file|awk '{print $1}'"); +$MD5 = md5_file($config_file); +for ($i=0; $i < $INTERVAL*6 ; $i++) { + sleep(10); + if (md5_file($config_file) != $MD5){syslog(LOG_INFO, "config file updated, reloading."); $i=10000;} +} +debug("Sleeped ".(time()-$time1)." seconds."); + +###### END OF SECTION ###### +};};?> + diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmi_event_delete.php b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmi_event_delete.php new file mode 100644 index 00000000..aec2995d --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmi_event_delete.php @@ -0,0 +1,5 @@ + diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_array.php b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_array.php deleted file mode 100644 index d1381261..00000000 --- a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_array.php +++ /dev/null @@ -1,10 +0,0 @@ -/dev/null"; -exec($command, $output); -$array = array(); -for ($i = 0; $i < sizeof($output); $i++) { - $value = explode(",", $output[$i]); - $array[] = $value; -} -echo json_encode($array); -?> diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_events.php b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_events.php new file mode 100644 index 00000000..695f8c3b --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_events.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_helpers.php b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_helpers.php new file mode 100644 index 00000000..2c3c39a6 --- /dev/null +++ b/source/ipmitool-plugin/usr/local/emhttp/plugins/ipmitool-plugin/include/ipmitool_helpers.php @@ -0,0 +1,98 @@ + /dev/null`/exe ] && echo 'yes' || echo 'no' 2> /dev/null" )); + +// get ip address of local ipmi +$ipmitool_lanip = trim(shell_exec("/usr/bin/ipmitool lan print | grep 'IP Address ' | sed -n -e 's/^.*: //p'")); + +// use save ip address or use local ipmi address +$ipmitool_ipaddr = preg_match('/^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/', $ipmitool_cfg['IPADDR']) ? $ipmitool_cfg['IPADDR'] : $ipmitool_lanip; + +$ipmitool_cpu = isset($ipmitool_cfg['CPU_TEMP']) ? $ipmitool_cfg['CPU_TEMP'] : ""; // cpu temp display name +$ipmitool_mb = isset($ipmitool_cfg['MB_TEMP']) ? $ipmitool_cfg['MB_TEMP'] : ""; // mb temp display name +$ipmitool_fan = isset($ipmitool_cfg['IPMI_FAN']) ? $ipmitool_cfg['IPMI_FAN'] : ""; // fan speed display name +$ipmitool_user = isset($ipmitool_cfg['USER']) ? $ipmitool_cfg['USER'] : ""; // user for remote access +$ipmitool_password = isset($ipmitool_cfg['PASSWORD']) ? $ipmitool_cfg['PASSWORD'] : ""; // password for remote access + +// options for remote access or not +$ipmitool_options = ($remote == "enable") ? " -I lanplus -H '$ipmitool_ipaddr' -U '$ipmitool_user' -P '". + base64_decode($ipmitool_password)."' " : ""; + +/* get an array of all sensors and their values */ +function ipmi_sensors($options) { + $cmd = "/usr/bin/ipmitool -vc sdr $options 2>/dev/null"; + exec($cmd, $output); + + // key names for ipmitool sensor output + $sensor_keys = array('Name','Reading','Units','Status','Entity','Location','Type','Nominal', + 'NormalMin','NormalMax','UpperNonRec','UpperCritical','UpperNonCritical','LowerNonRec', + 'LowerCritical','LowerNonCritical','MinRange','MaxRange' ); + + $sensors_array = []; + + foreach($output as $sensor){ + + // add sensor keys as keys to ipmitool output + $sensor_array = array_combine($sensor_keys, array_slice(explode(",", $sensor),0,18,true)); + + // add sensor to array of sensors + $sensors_array[] = $sensor_array; + } + return $sensors_array; +} + +/* get array of events and their values */ +function ipmi_events($options){ + $cmd = "/usr/bin/ipmitool -c sel elist $options 2>/dev/null"; + exec($cmd, $output); + + // key names for ipmitool event output + $event_keys = array('Event','Datestamp','Timestamp','Sensor','Description','Status'); + + $events_array = []; + + foreach($output as $event){ + + // add event keys as keys to ipmitool output cut to match + $event_array = array_combine($event_keys, array_slice(explode(",", $event),0,6,true)); + + $events_array[] = $event_array; + } + return $events_array; +} + +/* get select options for a given sensor type */ +function ipmi_get_options($selected, $type, $options){ + $sensors_array = ipmi_sensors($options); + $options = "\n"; + foreach($sensors_array as $sensor){ + if ($sensor["Type"] == $type && $sensor["Status"] != "ns"){ + $name = $sensor["Name"]; + $options .= "