diff options
author | Daniel Dickinson <lede@cshore.thecshore.com> | 2016-08-13 20:35:01 -0400 |
---|---|---|
committer | Daniel F. Dickinson <cshored@thecshore.com> | 2018-08-29 01:03:17 -0400 |
commit | fb262ad268ce7de9de79d47145c434e2662f2941 (patch) | |
tree | 9ffd72199ba22ea7b67bd62484cc459418c45398 /applications | |
parent | b93d3f3a1812e05def960835d39080780edb7129 (diff) |
luci-app-nut: Add support for NUT configuration
Adds app to configure NUT (Network UPS Tools), including
nut-server, nut-monitor, and nut-cgi.
Signed-off-by: Daniel F. Dickinson <cshored@thecshore.com>
Diffstat (limited to 'applications')
-rw-r--r-- | applications/luci-app-nut/Makefile | 16 | ||||
-rw-r--r-- | applications/luci-app-nut/luasrc/controller/nut.lua | 25 | ||||
-rw-r--r-- | applications/luci-app-nut/luasrc/model/cbi/nut_cgi.lua | 44 | ||||
-rw-r--r-- | applications/luci-app-nut/luasrc/model/cbi/nut_monitor.lua | 241 | ||||
-rw-r--r-- | applications/luci-app-nut/luasrc/model/cbi/nut_server.lua | 191 | ||||
-rwxr-xr-x | applications/luci-app-nut/root/etc/uci-defaults/40_luci-nut | 22 |
6 files changed, 539 insertions, 0 deletions
diff --git a/applications/luci-app-nut/Makefile b/applications/luci-app-nut/Makefile new file mode 100644 index 000000000..b5c5b0d4c --- /dev/null +++ b/applications/luci-app-nut/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Network UPS Tools Configuration +LUCI_PKGARCH:=all +PKG_RELEASE:=1 + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/applications/luci-app-nut/luasrc/controller/nut.lua b/applications/luci-app-nut/luasrc/controller/nut.lua new file mode 100644 index 000000000..5598451d6 --- /dev/null +++ b/applications/luci-app-nut/luasrc/controller/nut.lua @@ -0,0 +1,25 @@ +-- Copyright 2015 Daniel Dickinson <openwrt@daniel.thecshore.com> +-- Licensed to the public under the Apache License 2.0. + +module("luci.controller.nut", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/nut_server") and not nixio.fs.access("/etc/config/nut_monitor") and not nixio.fs.access("/etc/config/nut_cgi") then + return + end + + entry({"admin", "services", "nut"}, firstchild(), _("Network UPS Tools")) + + if nixio.fs.access("/etc/config/nut_server") then + entry({"admin", "services", "nut", "server"}, cbi("nut_server"), _("Network UPS Tools (Server)"), 20) + end + + if nixio.fs.access("/etc/config/nut_monitor") then + entry({"admin", "services", "nut", "monitor"}, cbi("nut_monitor"), _("Network UPS Tools (Monitor)"), 30) + end + + if nixio.fs.access("/etc/config/nut_cgi") then + entry({"admin", "services", "nut", "cgi"}, cbi("nut_cgi"), _("Network UPS Tools (CGI)"), 40) + end +end + diff --git a/applications/luci-app-nut/luasrc/model/cbi/nut_cgi.lua b/applications/luci-app-nut/luasrc/model/cbi/nut_cgi.lua new file mode 100644 index 000000000..9afa2ed24 --- /dev/null +++ b/applications/luci-app-nut/luasrc/model/cbi/nut_cgi.lua @@ -0,0 +1,44 @@ +-- Copyright 2015 Daniel Dickinson <openwrt@daniel.thecshore.com> +-- Licensed to the public under the Apache License 2.0. + +local m, s, o + +m = Map("nut_cgi", translate("Network UPS Tools (CGI)"), + translate("Network UPS Tools CGI Configuration")) + +s = m:section(SimpleSection, translate("NUT CGI Access")) +s.addremove = false +s.anonymous = true + +o = s:option(DummyValue, "nut_cgi_go", '<a href="/nut">' .. translate("Go to NUT CGI") .. '</a>') +o.section = "cbi-nut_cgi" + +s = m:section(TypedSection, "host", translate("Host")) +s.addremove = true +s.anonymous = true + +o = s:option(Value, "upsname", translate("UPS name"), translate("As configured by NUT")) +o.optional = false + +o = s:option(Value, "hostname", translate("Hostname or IP address")) +o.optional = false +o.datatype = "host" + +o = s:option(Value, "port", translate("Port")) +o.datatype = "port" +o.optional = true +o.placeholder = 3493 + +o = s:option(Value, "displayname", translate("Display name")) +o.optional = false + +s = m:section(TypedSection, "upsset", translate("Control UPS via CGI")) +s.addremove = false +s.anonymous = true +s.optional = false + +o = s:option(Flag, "enable", translate("Enable")) +o.optional = false +o.default = false + +return m diff --git a/applications/luci-app-nut/luasrc/model/cbi/nut_monitor.lua b/applications/luci-app-nut/luasrc/model/cbi/nut_monitor.lua new file mode 100644 index 000000000..0eda5d83e --- /dev/null +++ b/applications/luci-app-nut/luasrc/model/cbi/nut_monitor.lua @@ -0,0 +1,241 @@ +-- Copyright 2015 Daniel Dickinson <openwrt@daniel.thecshore.com> +-- Licensed to the public under the Apache License 2.0. + +local m, s, o +require "luci.util" + +m = Map("nut_monitor", translate("Network UPS Tools (Monitor)"), + translate("Network UPS Tools Monitoring Configuration")) + +s = m:section(NamedSection, "upsmon", "upsmon", translate("Global Settings")) +s.addremove = true +s.optional = true + +o = s:option(Value, "runas", translate("RunAs User"), translate("upsmon drops privileges to this user")) +o.placeholder = "nutmon" + +o = s:option(Value, "minsupplies", translate("Minimum required number or power supplies")) +o.datatype = "uinteger" +o.placeholder = 1 +o.optional = true + +o = s:option(Value, "shutdowncmd", translate("Shutdown command")) +o.optional = true +o.placeholder = "/sbin/halt" + +o = s:option(Value, "notifycmd", translate("Notify command")) +o.optional = true + +o = s:option(Value, "pollfreq", translate("Poll frequency")) +o.datatype = "uinteger" +o.placeholder = 5 +o.optional = true + +o = s:option(Value, "pollfreqalert", translate("Poll frequency alert")) +o.datatype = "uinteger" +o.optional = true +o.placeholder = 5 + +o = s:option(Value, "hotsync", translate("Hot Sync")) +o.optional = true +o.placeholder = 15 + +o = s:option(Value, "deadtime", translate("Deadtime")) +o.datatype = "uinteger" +o.optional = true +o.placeholder = 15 + +o = s:option(Value, "onlinemsg", translate("Online message")) +o.optional = true + +o = s:option(Value, "onbattmsg", translate("On battery message")) +o.optional = true + +o = s:option(Value, "lowbattmsg", translate("Low battery message")) +o.optional = true + +o = s:option(Value, "fsdmsg", translate("Forced shutdown message")) +o.optional = true + +o = s:option(Value, "comokmsg", translate("Communications restored message")) +o.optional = true + +o = s:option(Value, "combadmsg", translate("Communications lost message")) +o.optional = true + +o = s:option(Value, "shutdownmsg", translate("Shutdown message")) +o.optional = true + +o = s:option(Value, "replbattmsg", translate("Replace battery message")) +o.optional = true + +o = s:option(Value, "nocommsg", translate("No communications message")) +o.optional = true + +o = s:option(Value, "noparentmsg", translate("No parent message")) +o.optional = true + +validatenotify = function(self, value) + val = StaticList.validate(self, value) + if val then + for k, v in pairs(val) do + if (v == 'IGNORE') then + return nil, "Ignore must the only option selected, when selected" + end + end + end + return val +end + +o = s:option(StaticList, "defaultnotify", translate("Notification defaults")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.default = "SYSLOG" +o.validate = validatenotify + +o = s:option(StaticList, "onlinenotify", translate("Notify when back online")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "onbattnotify", translate("Notify when on battery")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "nowbattnotify", translate("Notify when low battery")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "nowbattnotify", translate("Notify when low battery")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "fsdnotify", translate("Notify when force shutdown")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "comoknotify", translate("Notify when communications restored")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "combadnotify", translate("Notify when communications lost")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "shutdownotify", translate("Notify when shutting down")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +o = s:option(StaticList, "replbattnotify", translate("Notify when battery needs replacing")) +o.optional = true +o.widget = "select" +o:value("EXEC", translate("Execute notify command")) +o:value("SYSLOG", translate("Write to syslog")) +o:value("IGNORE", translate("Ignore")) +o.validate = validatenotify + +local have_ssl_support = luci.util.checklib("/usr/sbin/upsmon", "libssl.so") + +if have_ssl_support then + o = s:option(Value, "certpath", translate("CA Certificate path"), translate("Path containing ca certificates to match against host certificate")) + o.optional = true + o.placeholder = "/etc/ssl/certs" + + o = s:option(Flag, "certverify", translate("Verify all connection with SSL"), translate("Require SSL and make sure server CN matches hostname")) + o.optional = true + o.default = false +end + +s = m:section(TypedSection, "master", translate("UPS Master")) +s.optional = true +s.addremove = true +s.anonymous = true + +o = s:option(Value, "upsname", translate("Name of UPS"), translate("As configured by NUT")) +o.optional = false + +o = s:option(Value, "hostname", translate("Hostname or address of UPS")) +o.optional = false +s.datetype = "host" + +o = s:option(Value, "port", translate("Port")) +o.optional = true +o.placeholder = 3493 +o.datatype = "port" + +o = s:option(Value, "powervalue", translate("Power value")) +o.optional = false +o.datatype = "uinteger" +o.default = 1 + +o = s:option(Value, "username", translate("Username")) +o.optional = false + +o = s:option(Value, "password", translate("Password")) +o.optional = false +o.password = true + +s = m:section(TypedSection, "slave", translate("UPS Slave")) +s.optional = true +s.addremove = true +s.anonymous = true + +o = s:option(Value, "upsname", translate("Name of UPS"), translate("As configured by NUT")) +o.optional = false + +o = s:option(Value, "hostname", translate("Hostname or address of UPS")) +o.optional = false +s.datetype = "host" + +o = s:option(Value, "port", translate("Port")) +o.optional = true +o.placeholder = 3493 +o.datatype = "port" + +o = s:option(Value, "powervalue", translate("Power value")) +o.optional = false +o.datatype = "uinteger" +o.default = 1 + +o = s:option(Value, "username", translate("Username")) +o.optional = false + +o = s:option(Value, "password", translate("Password")) +o.optional = false +o.password = true + +return m diff --git a/applications/luci-app-nut/luasrc/model/cbi/nut_server.lua b/applications/luci-app-nut/luasrc/model/cbi/nut_server.lua new file mode 100644 index 000000000..dea793239 --- /dev/null +++ b/applications/luci-app-nut/luasrc/model/cbi/nut_server.lua @@ -0,0 +1,191 @@ +-- Copyright 2015 Daniel Dickinson <openwrt@daniel.thecshore.com> +-- Licensed to the public under the Apache License 2.0. + +local m, s, o + +local nixio = require "nixio" +require "luci.util" + +m = Map("nut_server", translate("Network UPS Tools (Server)"), + translate("Network UPS Tools Server Configuration")) + +s = m:section(TypedSection, "user", translate("NUT Users")) +s.addremove = true +s.anonymous = true + +o = s:option(Value, "username", translate("Username")) +o.optional = false + +o = s:option(Value, "password", translate("Password")) +o.password = true +o.optional = false + +o = s:option(MultiValue, "actions", translate("Allowed actions")) +o.widget = "select" +o:value("set", translate("Set variables")) +o:value("fsd", translate("Forced Shutdown")) +o.optional = true + +o = s:option(DynamicList, "instcmd", translate("Instant commands"), translate("Use upscmd -l to see full list which the commands your UPS supports (requires upscmd package)")) +o.optional = true + +o = s:option(ListValue, "upsmon", translate("Role")) +o:value("slave", translate("Slave")) +o:value("master", translate("Master")) +o.optional = false + +s = m:section(TypedSection, "listen_address", translate("Addresses on which to listen")) +s.addremove = true +s.anonymous = true + +o = s:option(Value, "address", translate("IP Address")) +o.optional = false +o.datatype = "ipaddr" +o.placeholder = "127.0.0.1" + +o = s:option(Value, "port", translate("Port")) +o.optional = true +o.datatype = "port" +o.placeholder = "3493" + +s = m:section(NamedSection, "upsd", "upsd", translate("Global Settings")) +s.addremove = true + +o = s:option(Value, "maxage", translate("Maximum Age of Data"), translate("Period after which data is considered stale")) +o.datatype = "uinteger" +o.optional = true +o.placeholder = 15 + +o = s:option(Value, "runas", translate("RunAs User"), translate("Drop privileges to this user")) +o.optional = true +o.placeholder = "nut" + +o = s:option(Value, "statepath", translate("Path to state file")) +o.optional = true +o.placeholder = "/var/run/nut" + +o = s:option(Value, "maxconn", translate("Maximum connections")) +o.optional = true +o.datatype = "uinteger" +o.placeholder = 24 + +if luci.util.checklib("/usr/sbin/upsd", "libssl.so") then + o = s:option(Value, "certfile", translate("Certificate file (SSL)")) + o.optional = true +end + +s = m:section(TypedSection, "driver", translate("Driver Configuration"), + translate("The name of this section will be used as UPS name elsewhere")) +s.addremove = true +s.anonymous = false + +driverlist = nixio.fs.dir("/lib/nut") + +o = s:option(ListValue, "driver", translate("Driver")) +for driver in driverlist do + o:value(driver) +end +o.optional = false + +o = s:option(Value, "port", translate("Port")) +o.optional = false +o.default = "auto" + +o = s:option(Value, "mfr", translate("Manufacturer (Display)")) +o.optional = true + +o = s:option(Value, "model", translate("Model (Display)")) +o.optional = true + +o = s:option(Value, "serial", translate("Serial Number")) +o.optional = true + +o = s:option(Value, "sdtime", translate("Additional Shutdown Time(s)")) +o.optional = true + +o = s:option(Value, "offdelay", translate("Off Delay(s)"), translate("Delay for kill power command")) +o.optional = true +o.placeholder = 20 + +n = s:option(Value, "ondelay", translate("On Delay(s)"), translate("Delay to power on UPS if power returns after kill power")) +n.optional = true +n.placeholder = 30 + +function o.validate(self, cfg, value) + if n:cfgvalue(cfg) <= value then + return nil + end +end + +function n.validate(self, cfg, value) + if o:cfgvalue(cfg) >= value then + return nil + end +end + +o = s:option(Value, "pollfreq", translate("Polling Frequency(s)")) +o.optional = true +o.datatype = "integer" +o.placeholder = 30 + +o = s:option(Value, "vendor", translate("Vendor (regex)")) +o.optional = true + +o = s:option(Value, "product", translate("Product (regex)")) +o.optional = true + +o = s:option(Value, "bus", translate("USB Bus(es) (regex)")) +o.optional = true +o.datatype = "uinteger" + +o = s:option(Flag, "interruptonly", translate("Interrupt Only")) +o.optional = true +o.default = false + +o = s:option(Value, "interruptsize", translate("Interrupt Size"), translate("Bytes to read from interrupt pipe")) +o.optional = true +o.datatype = "integer" + +o = s:option(Value, "maxreport", translate("Max USB HID Length Reported"), translate("Workaround for buggy firmware")) +o.optional = true +o.datatype = "integer" +o.default = nil + +o = s:option(Value, "vendorid", translate("USB Vendor Id")) +o.optional = true + +o = s:option(Value, "productid", translate("USB Product Id")) +o.optional = true + +o = s:option(Value, "runas", translate("RunAs User"), translate("User as which to execute driver; requires device file accessed by driver be read-write for that user.")) +o.optional = true +o.placeholder = "nut" + +o = s:option(Value, "community", translate("SNMP Community")) +o.optional = true +o.placeholder = "private" + +o = s:option(ListValue, "snmp_version", translate("SNMP version")) +o.optional = true +o:value("v1", translate("SNMPv1")) +o:value("v2c", translate("SNMPv2c")) +o:value("v3", translate("SNMPv3")) +o:value("", "") +o.default = "" + +o = s:option(Value, "snmp_retries", translate("SNMP retries")) +o.optional = true +o.datatype = "uinteger" + +o = s:option(Value, "snmp_timeout", translate("SNMP timeout(s)")) +o.optional = true +o.datatype = "uinteger" + +o = s:option(Flag, "notransferoids", translate("No low/high voltage transfer OIDs")) +o.optional = true +o.default = false + +o = s:option(Value, "other", translate("Additional Parameters")) +o.optional = true + +return m diff --git a/applications/luci-app-nut/root/etc/uci-defaults/40_luci-nut b/applications/luci-app-nut/root/etc/uci-defaults/40_luci-nut new file mode 100755 index 000000000..621f6a6a3 --- /dev/null +++ b/applications/luci-app-nut/root/etc/uci-defaults/40_luci-nut @@ -0,0 +1,22 @@ +#!/bin/sh + +version="$(opkg status nut|grep 'Version: '|cut -f2 -d\ )" +release="$(echo $version|cut -f2 -d-)" + +if [ "$version" = "2.7.4" ] && [ "$release" -lt 8 ]; then + uci -q batch <<-EOF >/dev/null + delete ucitrack.@nut_server[-1] + delete ucitrack.@nut_monitor[-1] + delete ucitrack.@nut_cgi[-1] + add ucitrack nut_server + set ucitrack.@nut_server[-1].init=nut-server + add ucitrack nut_monitor + set ucitrack.@nut_monitor[-1].init=nut-monitor + add ucitrack nut_cgi + set ucitrack.@nut_cgi[-1].init=nut-cgi + commit ucitrack +EOF +fi + +rm -f /tmp/luci-indexcache +exit 0 |