v1.0. Luaposix, multiple service instances.

This commit is contained in:
gSpot
2023-05-01 14:39:23 +03:00
parent 642265b96d
commit 76acd939a9
24 changed files with 1515 additions and 988 deletions

View File

@@ -1,11 +1,11 @@
#
# (с) 2021 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
# (с) 2023 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
#
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector
PKG_VERSION:=0.6
PKG_VERSION:=1.0
PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
@@ -17,17 +17,19 @@ define Package/$(PKG_NAME)
TITLE:=Internet detector
URL:=https://github.com/gSpotx2f/luci-app-internet-detector
PKGARCH:=all
DEPENDS:=+lua +luci-lib-nixio +libuci-lua
DEPENDS:=+lua +luaposix +libuci-lua
endef
define Package/$(PKG_NAME)/description
Internet-detector is a small daemon
for checking Internet availability.
Written in Lua using the nixio library.
Written in Lua using the luaposix library.
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/internet-detector
/etc/internet-detector/down-script.internet
/etc/internet-detector/up-script.internet
endef
define Build/Configure
@@ -40,8 +42,8 @@ define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/internet-detector $(1)/etc/config/internet-detector
$(INSTALL_DIR) $(1)/etc/internet-detector
$(INSTALL_BIN) ./files/etc/internet-detector/down-script $(1)/etc/internet-detector/down-script
$(INSTALL_BIN) ./files/etc/internet-detector/up-script $(1)/etc/internet-detector/up-script
$(INSTALL_DATA) ./files/etc/internet-detector/down-script.internet $(1)/etc/internet-detector/down-script.internet
$(INSTALL_DATA) ./files/etc/internet-detector/up-script.internet $(1)/etc/internet-detector/up-script.internet
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/internet-detector $(1)/etc/init.d/internet-detector
$(INSTALL_DIR) $(1)/usr/bin

View File

@@ -1,52 +1,48 @@
config main 'config'
option mode '2'
option mode '1'
option enable_logger '1'
config ui 'ui'
list hosts '8.8.8.8'
list hosts '1.1.1.1'
option check_type '0'
option tcp_port '53'
option ui_interval_up '6'
option ui_interval_down '1'
option ui_connection_attempts '1'
option ui_connection_timeout '1'
option service_interval_up '30'
option service_interval_down '5'
option service_connection_attempts '2'
option service_connection_timeout '2'
option service_enable_logger '1'
option interval_up '6'
option interval_down '1'
option connection_attempts '1'
option connection_timeout '1'
config module 'mod_led_control'
option enabled '0'
config module 'mod_reboot'
option enabled '0'
option dead_period '3600'
option force_reboot_delay '300'
config module 'mod_network_restart'
option enabled '0'
option dead_period '900'
option attempts '1'
option restart_timeout '0'
config module 'mod_modem_restart'
option enabled '0'
option dead_period '600'
option any_band '0'
config module 'mod_public_ip'
option enabled '0'
option provider 'opendns1'
option interval '600'
option timeout '3'
config module 'mod_email'
option enabled '0'
option alive_period '0'
option mail_smtp 'smtp.gmail.com'
option mail_smtp_port '587'
option mail_security 'tls'
config module 'mod_user_scripts'
option enabled '0'
option alive_period '0'
option dead_period '0'
config instance 'internet'
option enabled '1'
list hosts '8.8.8.8'
list hosts '1.1.1.1'
option check_type '0'
option tcp_port '53'
option interval_up '30'
option interval_down '5'
option connection_attempts '2'
option connection_timeout '2'
option mod_led_control_enabled '0'
option mod_reboot_enabled '0'
option mod_reboot_dead_period '3600'
option mod_reboot_force_reboot_delay '300'
option mod_network_restart_enabled '0'
option mod_network_restart_dead_period '900'
option mod_network_restart_attempts '1'
option mod_network_restart_restart_timeout '0'
option mod_modem_restart_enabled '0'
option mod_modem_restart_dead_period '600'
option mod_modem_restart_any_band '0'
option mod_public_ip_enabled '0'
option mod_public_ip_provider 'opendns1'
option mod_public_ip_qtype '0'
option mod_public_ip_interval '600'
option mod_public_ip_timeout '3'
option mod_email_enabled '0'
option mod_email_alive_period '0'
option mod_email_mail_smtp 'smtp.gmail.com'
option mod_email_mail_smtp_port '587'
option mod_email_mail_security 'tls'
option mod_user_scripts_enabled '0'
option mod_user_scripts_alive_period '0'
option mod_user_scripts_dead_period '0'

View File

@@ -3,17 +3,23 @@
START=97
STOP=01
ID="/usr/bin/internet-detector"
PROG=/usr/bin/internet-detector
config_app() {
config_get enabled "$1" enabled "0"
if [ $enabled = "1" ]; then
$PROG service "$1"
fi
}
start() {
$ID
config_load internet-detector
config_get mode "config" mode "0"
if [ $mode = "1" ]; then
config_foreach config_app "instance"
fi
}
stop() {
$ID stop
}
restart() {
stop
start
$PROG stop
}

View File

@@ -5,112 +5,103 @@
Dependences:
lua
luci-lib-nixio
luaposix
libuci-lua
(с) 2021 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
(с) 2023 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
--]]
-- Default settings
local Config = {
mode = 2,
enableLogger = true,
intervalUp = 30,
intervalDown = 5,
connectionAttempts = 2,
connectionTimeout = 2,
UIConnectionAttempts = 1,
UIConnectionTimeout = 1,
hosts = {
[1] = "8.8.8.8",
[2] = "1.1.1.1",
},
tcpPort = 53,
pingPacketSize = 56,
iface = nil,
checkType = 0, -- 0: TCP, 1: ping
hostname = "OpenWrt",
appName = "internet-detector",
commonDir = "/tmp/run",
debugLog = "/tmp/internet-detector.debug",
pingCmd = "/bin/ping",
pingParams = "-c 1",
debug = false,
modules = {},
parsedHosts = {},
}
Config.configDir = string.format("/etc/%s", Config.appName)
Config.modulesDir = string.format("/usr/lib/%s", Config.appName)
Config.pidFile = string.format("%s/%s.pid", Config.commonDir, Config.appName)
Config.statusFile = string.format("%s/%s.status", Config.commonDir, Config.appName)
-- Importing packages
local function prequire(package)
local dirent = require("posix.dirent")
local fcntl = require("posix.fcntl")
local signal = require("posix.signal")
local socket = require("posix.sys.socket")
local stat = require("posix.sys.stat")
local syslog = require("posix.syslog")
local time = require("posix.time")
local unistd = require("posix.unistd")
local uci = require("uci")
-- Default settings
local InternetDetector = {
mode = 0,
enableLogger = true,
hostname = "OpenWrt",
appName = "internet-detector",
commonDir = "/tmp/run",
pingCmd = "/bin/ping",
pingParams = "-c 1",
debug = false,
serviceConfig = {
hosts = {
[1] = "8.8.8.8",
[2] = "1.1.1.1",
},
check_type = 0, -- 0: TCP, 1: ICMP
tcp_port = 53,
icmp_packet_size = 56,
interval_up = 30,
interval_down = 5,
connection_attempts = 2,
connection_timeout = 2,
iface = nil,
instance = nil,
},
modules = {},
parsedHosts = {},
}
InternetDetector.configDir = string.format("/etc/%s", InternetDetector.appName)
InternetDetector.modulesDir = string.format("/usr/lib/%s", InternetDetector.appName)
-- Loading settings from UCI
local uciCursor = uci.cursor()
InternetDetector.mode = tonumber(
uciCursor:get(InternetDetector.appName, "config", "mode"))
InternetDetector.enableLogger = (tonumber(
uciCursor:get(InternetDetector.appName, "config", "enable_logger")) ~= 0)
local hostname = uciCursor:get("system", "@[0]", "hostname")
if hostname ~= nil then
InternetDetector.hostname = hostname
end
local RUNNING
function InternetDetector:prequire(package)
local retVal, pkg = pcall(require, package)
return retVal and pkg
end
local nixio = prequire("nixio")
if not nixio then
error("You need to install nixio...")
function InternetDetector:loadUCIConfig(sType, instance)
local success
local num = 0
uciCursor:foreach(
self.appName,
sType,
function(s)
if s[".name"] == instance then
for k, v in pairs(s) do
if type(v) == "string" and v:match("^[%d]+$") then
v = tonumber(v)
end
self.serviceConfig[k] = v
end
success = true
self.serviceConfig.instanceNum = num
end
num = num + 1
end
)
self.serviceConfig.instance = instance
self.pidFile = string.format(
"%s/%s.%s.pid", self.commonDir, self.appName, instance)
self.statusFile = string.format(
"%s/%s.%s.status", self.commonDir, self.appName, instance)
return success
end
local uci = prequire("uci")
if not uci then
error("You need to install libuci-lua...")
end
-- Loading settings from UCI
local uciCursor = uci.cursor()
Config.mode = tonumber(uciCursor:get(
Config.appName, "config", "mode"))
Config.enableLogger = (tonumber(uciCursor:get(
Config.appName, "config", "service_enable_logger")) ~= 0)
Config.intervalUp = tonumber(uciCursor:get(
Config.appName, "config", "service_interval_up"))
Config.intervalDown = tonumber(uciCursor:get(
Config.appName, "config", "service_interval_down"))
Config.connectionAttempts = tonumber(uciCursor:get(
Config.appName, "config", "service_connection_attempts"))
Config.connectionTimeout = tonumber(uciCursor:get(
Config.appName, "config", "service_connection_timeout"))
Config.UIConnectionAttempts = tonumber(uciCursor:get(
Config.appName, "config", "ui_connection_attempts"))
Config.UIConnectionTimeout = tonumber(uciCursor:get(
Config.appName, "config", "ui_connection_timeout"))
Config.hosts = uciCursor:get(Config.appName, "config", "hosts")
local tcpPort = uciCursor:get(
Config.appName, "config", "tcp_port")
if tcpPort ~= nil then
Config.tcpPort = tonumber(tcpPort)
end
local pingPacketSize = uciCursor:get(
Config.appName, "config", "ping_packet_size")
if pingPacketSize ~= nil then
Config.pingPacketSize = tonumber(pingPacketSize)
end
local iface = uciCursor:get(
Config.appName, "config", "iface")
if iface ~= nil then
Config.iface = iface
end
Config.checkType = tonumber(uciCursor:get(
Config.appName, "config", "check_type"))
local hostname = uciCursor:get("system", "@[0]", "hostname")
if hostname ~= nil then
Config.hostname = hostname
end
local function writeValueToFile(filePath, str)
function InternetDetector:writeValueToFile(filePath, str)
local retValue = false
local fh = io.open(filePath, "w")
if fh then
@@ -122,7 +113,7 @@ local function writeValueToFile(filePath, str)
return retValue
end
local function readValueFromFile(filePath)
function InternetDetector:readValueFromFile(filePath)
local retValue
local fh = io.open(filePath, "r")
if fh then
@@ -132,72 +123,97 @@ local function readValueFromFile(filePath)
return retValue
end
local function statusJson(inet, t)
local lines = { [1] = string.format('"inet":%d', inet) }
function InternetDetector:statusJson(inet, instance, t)
local lines = { [1] = string.format(
'{"instance":"%s","num":"%d","inet":%d',
instance,
self.serviceConfig.instanceNum,
inet)}
if t then
for k, v in pairs(t) do
lines[#lines + 1] = string.format('"%s":"%s"', k, v)
end
end
return "{" .. table.concat(lines, ",") .. "}"
return table.concat(lines, ",") .. "}"
end
local function writeLogMessage(level, msg)
if Config.enableLogger then
nixio.syslog(level, msg)
function InternetDetector:writeLogMessage(level, msg)
if self.enableLogger then
local levels = {
emerg = syslog.LOG_EMERG,
alert = syslog.LOG_ALERT,
crit = syslog.LOG_CRIT,
err = syslog.LOG_ERR,
warning = syslog.LOG_WARNING,
notice = syslog.LOG_NOTICE,
info = syslog.LOG_INFO,
debug = syslog.LOG_DEBUG,
}
syslog.syslog(levels[level] or syslog.LOG_INFO, string.format(
"%s: %s", self.serviceConfig.instance or "", msg))
end
end
local function loadModules()
package.path = string.format("%s;%s/?.lua", package.path, Config.modulesDir)
Config.modules = {}
uciCursor:foreach(
Config.appName,
"module",
function(s)
local mod_name = s[".name"]
if mod_name and s.enabled == "1" then
local m = prequire(mod_name)
if m then
m.config = Config
m.syslog = writeLogMessage
m.writeValue = writeValueToFile
m.readValue = readValueFromFile
m:init(s)
Config.modules[#Config.modules + 1] = m
function InternetDetector:loadModules()
package.path = string.format("%s;%s/?.lua", package.path, self.modulesDir)
self.modules = {}
local ok, modulesDir = pcall(dirent.files, self.modulesDir)
if ok then
for item in modulesDir do
if item:match("^mod_") then
local modName = item:gsub("%.lua$", "")
local modConfig = {}
for k, v in pairs(self.serviceConfig) do
if k:match("^" .. modName) then
modConfig[k:gsub("^" .. modName .. "_", "")] = v
end
end
if modConfig.enabled == 1 then
local m = self:prequire(modName)
if m then
m.config = self
m.syslog = function(level, msg) self:writeLogMessage(level, msg) end
m.writeValue = function(filePath, str) return self:writeValueToFile(filePath, str) end
m.readValue = function(filePath) return self:readValueFromFile(filePath) end
m:init(modConfig)
self.modules[#self.modules + 1] = m
end
end
end
end
)
end
local function parseHost(host)
local addr, port = host:match("^([^:]+):?(%d*)")
return addr, tonumber(port) or false
end
local function parseHosts()
Config.parsedHosts = {}
for k, v in ipairs(Config.hosts) do
local addr, port = parseHost(v)
Config.parsedHosts[k] = { addr = addr, port = port }
end
end
local function pingHost(host)
function InternetDetector:parseHost(host)
local addr, port = host:match("^([^%[%]:]+):?(%d?%d?%d?%d?%d?)$")
if not addr then
addr, port = host:match("^%[?([^%[%]]+)%]?:?(%d?%d?%d?%d?%d?)$")
end
return addr, tonumber(port)
end
function InternetDetector:parseHosts()
self.parsedHosts = {}
for k, v in ipairs(self.serviceConfig.hosts) do
local addr, port = self:parseHost(v)
self.parsedHosts[k] = { addr = addr, port = port }
end
end
function InternetDetector:pingHost(host)
local ping = string.format(
"%s %s -W %d -s %d%s %s > /dev/null 2>&1",
Config.pingCmd,
Config.pingParams,
Config.connectionTimeout,
Config.pingPacketSize,
Config.iface and (" -I " .. Config.iface) or "",
self.pingCmd,
self.pingParams,
self.serviceConfig.connection_timeout,
self.serviceConfig.icmp_packet_size,
self.serviceConfig.iface and (" -I " .. self.serviceConfig.iface) or "",
host
)
local retCode = os.execute(ping)
-- Debug
if Config.debug then
if self.debug then
io.stdout:write(string.format(
"--- Ping ---\ntime = %s\n%s\nretCode = %s\n", os.time(), ping, retCode)
)
@@ -207,53 +223,94 @@ local function pingHost(host)
return retCode
end
local function TCPConnectionToHost(host, port)
local retCode = 1
local addrInfo = nixio.getaddrinfo(host, "any")
if addrInfo then
local family = addrInfo[1].family
if family then
local socket = nixio.socket(family, "stream")
socket:setopt("socket", "sndtimeo", Config.connectionTimeout)
socket:setopt("socket", "rcvtimeo", Config.connectionTimeout)
if Config.iface then
socket:setopt("socket", "bindtodevice", Config.iface)
end
local success = socket:connect(host, port or Config.tcpPort)
function InternetDetector:TCPConnectionToHost(host, port)
local retCode = 1
local saTable, errMsg, errNum = socket.getaddrinfo(host, port or self.serviceConfig.tcp_port)
-- Debug
if Config.debug then
local sockAddr, sockPort = socket:getsockname()
local peerAddr, peerPort = socket:getpeername()
if not saTable then
if self.debug then
io.stdout:write(string.format(
"GETADDRINFO ERROR: %s, %s\n", errMsg, errNum))
end
else
local family = saTable[1].family
if family then
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_STREAM, 0)
if not sock then
if self.debug then
io.stdout:write(string.format(
"SOCKET ERROR: %s, %s\n", errMsg, errNum))
end
return retCode
end
socket.setsockopt(sock, socket.SOL_SOCKET,
socket.SO_SNDTIMEO, self.serviceConfig.connection_timeout, 0)
socket.setsockopt(sock, socket.SOL_SOCKET,
socket.SO_RCVTIMEO, self.serviceConfig.connection_timeout, 0)
if self.serviceConfig.iface then
local ok, errMsg, errNum = socket.setsockopt(sock, socket.SOL_SOCKET,
socket.SO_BINDTODEVICE, self.serviceConfig.iface)
if not ok then
if self.debug then
io.stdout:write(string.format(
"SOCKET ERROR: %s, %s\n", errMsg, errNum))
end
return retCode
end
end
local success = socket.connect(sock, saTable[1])
if self.debug then
if not success then
io.stdout:write(string.format(
"SOCKET CONNECT ERROR: %s\n", tostring(success)))
end
local sockTable, err_s, e_s = socket.getsockname(sock)
local peerTable, err_p, e_p = socket.getpeername(sock)
if not sockTable then
sockTable = {}
io.stdout:write(
string.format("SOCKET ERROR: %s, %s\n", err_s, e_s))
end
if not peerTable then
peerTable = {}
io.stdout:write(
string.format("SOCKET ERROR: %s, %s\n", err_p, e_p))
end
io.stdout:write(string.format(
"--- TCP ---\ntime = %s\nconnectionTimeout = %s\niface = %s\nhost:port = %s:%s\nsockname = %s:%s\npeername = %s:%s\nsuccess = %s\n",
"--- TCP ---\ntime = %s\nconnection_timeout = %s\niface = %s\nhost:port = [%s]:%s\nsockname = [%s]:%s\npeername = [%s]:%s\nsuccess = %s\n",
os.time(),
Config.connectionTimeout,
tostring(Config.iface),
self.serviceConfig.connection_timeout,
tostring(self.serviceConfig.iface),
host,
port or Config.tcpPort,
tostring(sockAddr),
tostring(sockPort),
tostring(peerAddr),
tostring(peerPort),
port or self.serviceConfig.tcp_port,
tostring(sockTable.addr),
tostring(sockTable.port),
tostring(peerTable.addr),
tostring(peerTable.port),
tostring(success))
)
io.stdout:flush()
end
socket:close()
unistd.close(sock)
retCode = success and 0 or 1
end
end
return retCode
end
local function checkHosts()
local checkFunc = (Config.checkType == 1) and pingHost or TCPConnectionToHost
function InternetDetector:checkHosts()
local checkFunc = (self.serviceConfig.check_type == 1) and self.pingHost or self.TCPConnectionToHost
local retCode = 1
for k, v in ipairs(Config.parsedHosts) do
for i = 1, Config.connectionAttempts do
if checkFunc(v.addr, v.port) == 0 then
for k, v in ipairs(self.parsedHosts) do
for i = 1, self.serviceConfig.connection_attempts do
if checkFunc(self, v.addr, v.port) == 0 then
retCode = 0
break
end
@@ -265,37 +322,51 @@ local function checkHosts()
return retCode
end
local function main()
local lastStatus, currentStatus, timeNow, timeDiff, lastTime
local interval = Config.intervalUp
local counter = 0
function InternetDetector:breakMain(signo)
RUNNING = false
end
while true do
function InternetDetector:main()
signal.signal(signal.SIGTERM, function(signo) self:breakMain(signo) end)
signal.signal(signal.SIGINT, function(signo) self:breakMain(signo) end)
signal.signal(signal.SIGQUIT, function(signo) self:breakMain(signo) end)
local lastStatus, currentStatus, timeNow, timeDiff, lastTime
local interval = self.serviceConfig.interval_up
local counter = 0
local onStart = true
RUNNING = true
while RUNNING do
if counter == 0 or counter >= interval then
currentStatus = checkHosts()
if not nixio.fs.access(Config.statusFile, "r") then
writeValueToFile(Config.statusFile, statusJson(currentStatus))
currentStatus = self:checkHosts()
if onStart or not stat.stat(self.statusFile) then
self:writeValueToFile(self.statusFile, self:statusJson(
currentStatus, self.serviceConfig.instance))
onStart = false
end
if currentStatus == 0 then
interval = Config.intervalUp
interval = self.serviceConfig.interval_up
if lastStatus ~= nil and currentStatus ~= lastStatus then
writeValueToFile(Config.statusFile, statusJson(currentStatus))
writeLogMessage("notice", "Internet connected")
self:writeValueToFile(self.statusFile, self:statusJson(
currentStatus, self.serviceConfig.instance))
self:writeLogMessage("notice", "Connected")
end
else
interval = Config.intervalDown
interval = self.serviceConfig.interval_down
if lastStatus ~= nil and currentStatus ~= lastStatus then
writeValueToFile(Config.statusFile, statusJson(currentStatus))
writeLogMessage("notice", "Internet disconnected")
self:writeValueToFile(self.statusFile, self:statusJson(
currentStatus, self.serviceConfig.instance))
self:writeLogMessage("notice", "Disconnected")
end
end
counter = 0
end
timeDiff = 0
for _, e in ipairs(Config.modules) do
timeNow = nixio.sysinfo().uptime
for _, e in ipairs(self.modules) do
timeNow = time.clock_gettime(time.CLOCK_MONOTONIC).tv_sec
if lastTime then
timeDiff = timeDiff + timeNow - lastTime
else
@@ -306,142 +377,156 @@ local function main()
end
local modulesStatus = {}
for k, v in ipairs(Config.modules) do
for k, v in ipairs(self.modules) do
if v.status ~= nil then
modulesStatus[v.name] = v.status
end
end
if next(modulesStatus) then
writeValueToFile(Config.statusFile, statusJson(currentStatus, modulesStatus))
self:writeValueToFile(self.statusFile, self:statusJson(
currentStatus, self.serviceConfig.instance, modulesStatus))
end
lastStatus = currentStatus
nixio.nanosleep(1)
unistd.sleep(1)
counter = counter + 1
end
end
local function removeProcessFiles()
os.remove(Config.pidFile)
os.remove(Config.statusFile)
function InternetDetector:removeProcessFiles()
os.remove(string.format(
"%s/%s.%s.pid", self.commonDir, self.appName, self.serviceConfig.instance))
os.remove(string.format(
"%s/%s.%s.status", self.commonDir, self.appName, self.serviceConfig.instance))
end
local function status()
if nixio.fs.access(Config.pidFile, "r") then
return "running"
else
return "stoped"
end
end
local function poll(attempts, timeout)
if Config.mode == 1 then
Config.connectionAttempts = Config.UIConnectionAttempts
Config.connectionTimeout = Config.UIConnectionTimeout
end
if attempts then
Config.connectionAttempts = attempts
end
if timeout then
Config.connectionTimeout = timeout
end
if checkHosts() == 0 then
return statusJson(0)
else
return statusJson(1)
end
end
local function inetStatus(json)
local inetStat = 1
if nixio.fs.access(Config.statusFile, "r") then
local inetStatVal = readValueFromFile(Config.statusFile)
inetStat = inetStatVal
elseif Config.mode == 1 then
inetStat = poll()
else
os.exit(126)
end
if not json then
local sVal = inetStat:match('"inet":[0-9]')
if sVal then
sVal = sVal:match("[0-9]")
inetStat = (tonumber(sVal) == 0) and "up" or "down"
function InternetDetector:status()
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
local appName = self.appName:gsub("-", "%%-")
for item in commonDir do
if item:match("^" .. appName .. ".-%.pid$") then
return "running"
end
end
end
return "stoped"
end
function InternetDetector:poll()
local retCode = self:checkHosts()
return string.format('{"instances":[%s]}', self:statusJson(
retCode, self.serviceConfig.instance))
end
function InternetDetector:inetStatus()
local inetStat = '{"instances":[]}'
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
local appName = self.appName:gsub("-", "%%-")
local lines = {}
for item in commonDir do
if item:match("^" .. appName .. ".-%.status$") then
lines[#lines + 1] = self:readValueFromFile(
string.format("%s/%s", self.commonDir, item))
end
end
inetStat = '{"instances":[' .. table.concat(lines, ",") .. "]}"
end
return inetStat
end
local function stop()
local pidValue
if Config.enableLogger then
nixio.openlog(Config.appName)
end
if nixio.fs.access(Config.pidFile, "r") then
pidValue = readValueFromFile(Config.pidFile)
function InternetDetector:stopInstance(pidFile)
local retVal
if stat.stat(pidFile) then
pidValue = self:readValueFromFile(pidFile)
if pidValue then
local success
local ok, errMsg, errNum
for i = 0, 10 do
success = nixio.kill(tonumber(pidValue), 15)
if success then
ok, errMsg, errNum = signal.kill(tonumber(pidValue), signal.SIGTERM)
if ok then
break
end
end
if not success then
io.stderr:write(string.format('No such process: "%s"\n', pidValue))
if not ok then
io.stderr:write(string.format(
'Process stop error: %s (%s). PID: "%s"\n', errMsg, errNum, pidValue))
end
writeLogMessage("info", string.format("[%s] stoped", pidValue))
removeProcessFiles()
if errNum == 3 then
os.remove(pidFile)
end
retVal = true
end
end
if not pidValue then
io.stderr:write(
string.format('PID file "%s" does not exist. %s not running?\n',
Config.pidFile, Config.appName))
end
if Config.enableLogger then
nixio.closelog()
pidFile, self.appName))
end
return retVal
end
local function preRun()
-- Exit if internet-detector mode != 2(Service)
if Config.mode ~= 2 then
io.stderr:write(string.format('Start failed, mode != 2\n', Config.appName))
function InternetDetector:stop()
local appName = self.appName:gsub("-", "%%-")
local success
for i = 0, 10 do
success = true
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
for item in commonDir do
if item:match("^" .. appName .. ".-%.pid$") then
self:stopInstance(string.format("%s/%s", self.commonDir, item))
success = false
end
end
if success then
break
end
unistd.sleep(1)
else
break
end
end
end
function InternetDetector:preRun()
-- Exit if internet-detector mode != 1(Service)
if self.mode ~= 1 then
io.stderr:write(string.format('Start failed, mode != 1\n', self.appName))
os.exit(0)
end
if nixio.fs.access(Config.pidFile, "r") then
if stat.stat(self.pidFile) then
io.stderr:write(
string.format('PID file "%s" already exist. %s already running?\n',
Config.pidFile, Config.appName))
self.pidFile, self.appName))
return false
end
return true
end
local function run()
local pidValue = nixio.getpid()
writeValueToFile(Config.pidFile, pidValue)
if Config.enableLogger then
nixio.openlog(Config.appName, "pid")
function InternetDetector:run()
local pidValue = unistd.getpid()
self:writeValueToFile(self.pidFile, pidValue)
if self.enableLogger then
syslog.openlog(self.appName, syslog.LOG_PID, syslog.LOG_DAEMON)
end
writeLogMessage("info", "started")
loadModules()
self:writeLogMessage("info", "started")
self:loadModules()
-- Loaded modules
local modules = {}
for _, v in ipairs(Config.modules) do
for _, v in ipairs(self.modules) do
modules[#modules + 1] = string.format("%s", v.name)
end
if #modules > 0 then
writeLogMessage(
self:writeLogMessage(
"info", string.format("Loaded modules: %s", table.concat(modules, ", "))
)
end
-- Debug
if Config.debug then
if self.debug then
local function inspectTable()
local tables = {}, f
f = function(t, prefix)
@@ -459,92 +544,125 @@ local function run()
end
io.stdout:write("--- Config ---\n")
inspectTable()(Config, "Config.")
inspectTable()(self, "self.")
io.stdout:flush()
end
main()
if Config.enableLogger then
nixio.closelog()
self:writeValueToFile(
self.statusFile, self:statusJson(-1, self.serviceConfig.instance))
self:main()
self:removeProcessFiles()
if self.enableLogger then
self:writeLogMessage("info", "stoped")
syslog.closelog()
end
end
local function noDaemon()
if not preRun() then
function InternetDetector:noDaemon()
if not self:preRun() then
return
end
run()
self:run()
end
local function daemon(debug)
if not preRun() then
function InternetDetector:daemon()
if not self:preRun() then
return
end
-- UNIX double fork
if nixio.fork() == 0 then
nixio.setsid()
if nixio.fork() == 0 then
nixio.chdir("/")
nixio.umask(0)
local output = "/dev/null"
if debug then
output = Config.debugLog
Config.debug = true
end
if unistd.fork() == 0 then
unistd.setpid("s")
if unistd.fork() == 0 then
unistd.chdir("/")
stat.umask(0)
local devnull = fcntl.open("/dev/null", fcntl.O_RDWR)
io.stdout:flush()
io.stderr:flush()
nixio.dup(io.open("/dev/null", "r"), io.stdin)
nixio.dup(io.open(output, "a+"), io.stdout)
nixio.dup(io.open(output, "a+"), io.stderr)
run()
unistd.dup2(devnull, 0) -- io.stdin
unistd.dup2(devnull, 1) -- io.stdout
unistd.dup2(devnull, 2) -- io.stderr
self:run()
unistd.close(devnull)
end
os.exit(0)
end
os.exit(0)
end
local function restart()
stop()
daemon()
function InternetDetector:setServiceConfig(instance)
if self:loadUCIConfig("instance", instance) then
self:parseHosts()
return true
end
end
-- Main section
parseHosts()
local function help()
return string.format(
"Usage: %s [start|stop|restart|no-daemon|debug|status|inet-status|inet-status-json|poll [<attempts num>] [<timeout sec>]|--help]",
"Usage: %s service <UCI instance> | nodaemon <UCI instance> | debug <UCI instance> | stop | status | inet-status | poll [<attempts num>] [<timeout sec>] | --help",
arg[0]
)
end
local helpArgs = { ["-h"] = true, ["--help"] = true, ["help"] = true }
if arg[1] == "start" or #arg == 0 then
daemon()
elseif arg[1] == "no-daemon" then
noDaemon()
elseif arg[1] == "debug" then
daemon(true)
elseif arg[1] == "stop" then
stop()
elseif arg[1] == "restart" then
restart()
elseif arg[1] == "status" then
print(status())
elseif arg[1] == "inet-status" then
print(inetStatus())
elseif arg[1] == "inet-status-json" then
print(inetStatus(true))
elseif arg[1] == "poll" then
local attempts, timeout
if arg[2] and arg[2]:match("[0-9]+") then
attempts = tonumber(arg[2])
if arg[3] and arg[3]:match("[0-9]+") then
timeout = tonumber(arg[3])
if arg[1] == "service" then
if arg[2] then
if InternetDetector:setServiceConfig(arg[2]) then
InternetDetector:daemon()
else
os.exit(126)
end
else
print(help())
os.exit(1)
end
elseif arg[1] == "nodaemon" then
if arg[2] then
if InternetDetector:setServiceConfig(arg[2]) then
InternetDetector:noDaemon()
else
os.exit(126)
end
else
print(help())
os.exit(1)
end
elseif arg[1] == "debug" then
if arg[2] then
if InternetDetector:setServiceConfig(arg[2]) then
InternetDetector.debug = true
InternetDetector:noDaemon()
else
os.exit(126)
end
else
print(help())
os.exit(1)
end
elseif arg[1] == "stop" then
InternetDetector:stop()
elseif arg[1] == "status" then
print(InternetDetector:status())
elseif arg[1] == "inet-status" then
print(InternetDetector:inetStatus())
elseif arg[1] == "poll" then
if InternetDetector:loadUCIConfig("ui", "ui") then
InternetDetector:parseHosts()
if arg[2] and arg[2]:match("[0-9]+") then
InternetDetector.serviceConfig.connection_attempts = tonumber(arg[2])
if arg[3] and arg[3]:match("[0-9]+") then
InternetDetector.serviceConfig.connection_timeout = tonumber(arg[3])
end
end
print(InternetDetector:poll())
else
os.exit(126)
end
print(poll(attempts, timeout))
elseif helpArgs[arg[1]] then
print(help())
else

View File

@@ -2,11 +2,13 @@
Dependences:
mailsend
--]]
local nixio = require("nixio")
local unistd = require("posix.unistd")
local Module = {
name = "mod_email",
config = {},
config = {
debug = false,
},
syslog = function(level, msg) return true end,
writeValue = function(filePath, str) return false end,
readValue = function(filePath) return nil end,
@@ -45,7 +47,7 @@ function Module:init(t)
self.mailSmtpPort = t.mail_smtp_port
self.mailSecurity = t.mail_security
if nixio.fs.access(self.mta, "x") then
if unistd.access(self.mta, "x") then
self._enabled = true
else
self._enabled = false
@@ -66,16 +68,19 @@ end
function Module:sendMessage(msg)
local verboseArg = ""
-- Debug
if self.config.debug then
verboseArg = " -v"
io.stdout:write("--- mod_email ---\n")
io.stdout:write(string.format("--- %s ---\n", self.name))
io.stdout:flush()
end
local securityArgs = "-starttls -auth-login"
if self.mailSecurity == "ssl" then
securityArgs = "-ssl -auth"
end
local mtaCmd = string.format(
'%s%s %s -smtp "%s" -port %s -cs utf-8 -user "%s" -pass "%s" -f "%s" -t "%s" -sub "%s" -M "%s"',
self.mta, verboseArg, securityArgs, self.mailSmtp, self.mailSmtpPort,
@@ -102,12 +107,14 @@ function Module:run(currentStatus, lastStatus, timeDiff)
self._msgSent = false
self._lastConnection = nil
if not self._disconnected then
self._disconnected = true
self._disconnected = true
if not self._lastDisconnection then
self._lastDisconnection = os.date("%Y.%m.%d %H:%M:%S", os.time())
end
end
else
if not self._msgSent then
if not self._lastConnection then

View File

@@ -1,5 +1,6 @@
local nixio = require("nixio")
local unistd = require("posix.unistd")
local dirent = require("posix.dirent")
local Module = {
name = "mod_led_control",
@@ -20,13 +21,13 @@ local Module = {
}
function Module:resetLeds()
local dir = nixio.fs.dir(self.sysLedsDir)
if not dir then
local ok, dir = pcall(dirent.files, self.sysLedsDir)
if not ok then
return
end
for led in dir do
local brightness = string.format("%s/%s/brightness", self.sysLedsDir, led)
if nixio.fs.access(brightness, "w") then
if unistd.access(brightness, "w") then
self.writeValue(brightness, 0)
end
end
@@ -41,10 +42,11 @@ function Module:init(t)
self._ledMaxBrightnessFile = string.format("%s/max_brightness", self._ledDir)
self._ledBrightnessFile = string.format("%s/brightness", self._ledDir)
self._ledMaxBrightness = self.readValue(self._ledMaxBrightnessFile) or 1
if (not nixio.fs.access(self._ledDir, "r") or
not nixio.fs.access(self._ledBrightnessFile, "r", "w")) then
if (not unistd.access(self._ledDir, "r") or
not unistd.access(self._ledBrightnessFile, "rw")) then
self._enabled = false
self.syslog("warning", string.format("%s: LED '%s' is not available", self.name, self.ledName))
self.syslog("warning", string.format(
"%s: LED '%s' is not available", self.name, self.ledName))
else
self._enabled = true
-- Reset all LEDs
@@ -85,6 +87,7 @@ function Module:run(currentStatus, lastStatus, timeDiff)
self._counter = 0
end
self._counter = self._counter + timeDiff
end

View File

@@ -2,7 +2,7 @@
Dependences:
modemmanager
--]]
local nixio = require("nixio")
local unistd = require("posix.unistd")
local Module = {
name = "mod_modem_restart",
@@ -50,11 +50,11 @@ function Module:init(t)
self.iface = t.iface
self.anyBand = (tonumber(t.any_band) ~= 0)
if not nixio.fs.access(self.mmcli, "x") then
if not unistd.access(self.mmcli, "x") then
self.anyBand = false
end
if nixio.fs.access(self.mmInit, "x") then
if unistd.access(self.mmInit, "x") then
self._enabled = true
else
self._enabled = false

View File

@@ -1,5 +1,5 @@
local nixio = require("nixio")
local unistd = require("posix.unistd")
local Module = {
name = "mod_network_restart",
@@ -22,9 +22,9 @@ end
function Module:toggleDevice(flag)
local ip = "/sbin/ip"
if nixio.fs.access(ip, "x") then
return os.execute(
string.format("%s link set dev %s %s", ip, self.iface, (flag and "up" or "down"))
if unistd.access(ip, "x") then
return os.execute(string.format(
"%s link set dev %s %s", ip, self.iface, (flag and "up" or "down"))
)
end
end
@@ -71,10 +71,11 @@ function Module:run(currentStatus, lastStatus, timeDiff)
self.syslog("info", string.format(
"%s: restarting network interface '%s'", self.name, self.iface))
self:ifaceDown()
nixio.nanosleep(self.restartTimeout)
unistd.sleep(self.restartTimeout)
self:ifaceUp()
else
self.syslog("info", string.format("%s: restarting network", self.name))
self.syslog("info", string.format(
"%s: restarting network", self.name))
self:networkRestart()
end
self._deadCounter = 0

View File

@@ -1,79 +1,322 @@
local nixio = require("nixio")
local socket = require("posix.sys.socket")
local unistd = require("posix.unistd")
local Module = {
name = "mod_public_ip",
config = {},
syslog = function(level, msg) return true end,
writeValue = function(filePath, str) return false end,
readValue = function(filePath) return nil end,
runInterval = 600,
nslookup = "/usr/bin/nslookup",
timeout = 3,
providers = {
opendns1 = {
name = "opendns1", server = "208.67.222.222",
host = "myip.opendns.com", queryType = "a"
},
opendns2 = {
name = "opendns2", server = "208.67.220.220",
host = "myip.opendns.com", queryType = "a"
},
opendns3 = {
name = "opendns3", server = "208.67.222.220",
host = "myip.opendns.com", queryType = "a"
},
opendns4 = {
name = "opendns4", server = "208.67.220.222",
host = "myip.opendns.com", queryType = "a"
},
akamai = {
name = "akamai", server = "ns1-1.akamaitech.net",
host = "whoami.akamai.net", queryType = "a"
},
google = {
name = "google", server = "ns1.google.com",
host = "o-o.myaddr.l.google.com", queryType = "txt"
name = "mod_public_ip",
config = {
debug = false,
serviceConfig = {
iface = nil,
},
},
status = nil,
_provider = nil,
_nslookupCmd = nil,
_currentIp = nil,
_enabled = false,
_counter = 0,
syslog = function(level, msg) return true end,
writeValue = function(filePath, str) return false end,
readValue = function(filePath) return nil end,
port = 53,
runInterval = 600,
runIntervalFailed = 60,
timeout = 3,
reqAttempts = 3,
providers = {
opendns1 = {
name = "opendns1", host = "myip.opendns.com",
server = "208.67.222.222", server6 = "2620:119:35::35",
port = 53, queryType = "A", queryType6 = "AAAA",
},
opendns2 = {
name = "opendns2", host = "myip.opendns.com",
server = "208.67.220.220", server6 = "2620:119:35::35",
port = 53, queryType = "A", queryType6 = "AAAA",
},
opendns3 = {
name = "opendns3", host = "myip.opendns.com",
server = "208.67.222.220", server6 = "2620:119:35::35",
port = 53, queryType = "A", queryType6 = "AAAA",
},
opendns4 = {
name = "opendns4", host = "myip.opendns.com",
server = "208.67.220.222", server6 = "2620:119:35::35",
port = 53, queryType = "A", queryType6 = "AAAA",
},
akamai = {
name = "akamai", host = "whoami.akamai.net",
server = "ns1-1.akamaitech.net", server6 = "ns1-1.akamaitech.net",
port = 53, queryType = "A", queryType6 = "AAAA",
},
google = {
name = "google", host = "o-o.myaddr.l.google.com",
server = "ns1.google.com", server6 = "ns1.google.com",
port = 53, queryType = "TXT", queryType6 = "TXT",
},
},
status = nil,
_provider = nil,
_qtype = false,
_currentIp = nil,
_enabled = false,
_counter = 0,
_interval = 600,
_DNSPacket = nil,
}
function Module:parseA(str)
res = str:match("Name:%s+" .. self._provider.host .. "\nAddress:%s+[%w.:]+")
if res then
return res:match("[%w.:]+$")
function Module:getQueryType(type)
local types = {
A = 1,
NS = 2,
MD = 3,
MF = 4,
CNAME = 5,
SOA = 6,
MB = 7,
MG = 8,
MR = 9,
NULL = 10,
WKS = 11,
PTS = 12,
HINFO = 13,
MINFO = 14,
MX = 15,
TXT = 16,
AAAA = 28,
}
return types[type]
end
function Module:buildMessage(address, queryType)
if not queryType then
queryType = "A"
end
queryType = self:getQueryType(queryType)
local addressString = ""
for part in address:gmatch("[^.]+") do
local t = {}
for i in part:gmatch(".") do
t[#t + 1] = i
end
addrLen = #part
addrPart = table.concat(t)
addressString = addressString .. string.char(addrLen) .. addrPart
end
local data = (
string.char(
0xaa, 0xaa,
0x01, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
) ..
addressString ..
string.char(
0x00,
0x00, queryType,
0x00, 0x01
)
)
return data
end
function Module:sendUDPMessage(message, server, port)
local success
local retCode = 1
local data
if self.config.debug then
io.stdout:write(string.format("--- %s ---\n", self.name))
io.stdout:flush()
end
local saTable, errMsg, errNum = socket.getaddrinfo(server, port)
if not saTable then
if self.config.debug then
io.stdout:write(string.format(
"GETADDRINFO ERROR: %s, %s\n", errMsg, errNum))
end
else
local family = saTable[1].family
if family then
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_DGRAM, 0)
if not sock then
if self.config.debug then
io.stdout:write(string.format(
"SOCKET ERROR: %s, %s\n", errMsg, errNum))
end
return retCode
end
socket.setsockopt(sock, socket.SOL_SOCKET,
socket.SO_SNDTIMEO, self.timeout, 0)
socket.setsockopt(sock, socket.SOL_SOCKET,
socket.SO_RCVTIMEO, self.timeout, 0)
if self.config.serviceConfig.iface then
local ok, errMsg, errNum = socket.setsockopt(sock, socket.SOL_SOCKET,
socket.SO_BINDTODEVICE, self.config.serviceConfig.iface)
if not ok then
if self.config.debug then
io.stdout:write(string.format(
"SOCKET ERROR: %s, %s\n", errMsg, errNum))
end
return retCode
end
end
local ok, errMsg, errNum = socket.sendto(sock, message, saTable[1])
local response = {}
if ok then
local ret, resp, errNum = socket.recvfrom(sock, 1024)
data = ret
if data then
success = true
response = resp
elseif self.config.debug then
io.stdout:write(string.format(
"SOCKET RECV ERROR: %s, %s\n", tostring(resp), tostring(errNum)))
end
elseif self.config.debug then
io.stdout:write(string.format(
"SOCKET SEND ERROR: %s, %s\n", tostring(errMsg), tostring(errNum)))
end
if self.config.debug then
io.stdout:write(string.format(
"--- UDP ---\ntime = %s\nconnection_timeout = %s\niface = %s\nserver = %s:%s\nsockname = %s:%s\nsuccess = %s\n",
os.time(),
self.timeout,
tostring(self.config.serviceConfig.iface),
server,
tostring(port),
tostring(response.addr),
tostring(response.port),
tostring(success))
)
io.stdout:flush()
end
unistd.close(sock)
retCode = success and 0 or 1
end
end
return retCode, tostring(data)
end
function Module:parseParts(message, start, parts)
local partStart = start + 2
local partLen = message:sub(start, start + 1)
if #partLen == 0 then
return parts
end
local partEnd = partStart + (tonumber(partLen, 16) * 2)
parts[#parts + 1] = message:sub(partStart, partEnd - 1)
if message:sub(partEnd, partEnd + 1) == "00" or partEnd > #message then
return parts
else
return self:parseParts(message, partEnd, parts)
end
end
function Module:parseGoogle(str)
res = str:match(self._provider.host .. '%s+text%s+=%s+"[%w.:]+"')
if res then
return res:gsub('"', ''):match("[%w.:]+$")
function Module:decodeMessage(message)
local retTable = {}
local t = {}
for i = 1, #message do
t[#t + 1] = string.format("%.2x", string.byte(message, i))
end
message = table.concat(t)
local ANCOUNT = message:sub(13, 16)
local NSCOUNT = message:sub(17, 20)
local ARCOUNT = message:sub(21, 24)
local questionSectionStarts = 25
local questionParts = self:parseParts(message, questionSectionStarts, {})
local qtypeStarts = questionSectionStarts + (#table.concat(questionParts)) + (#questionParts * 2) + 1
local qclassStarts = qtypeStarts + 4
local answerSectionStarts = qclassStarts + 4
local numAnswers = math.max(
tonumber(ANCOUNT, 16), tonumber(NSCOUNT, 16), tonumber(ARCOUNT, 16))
if numAnswers > 0 then
for answerCount = 1, numAnswers do
if answerSectionStarts < #message then
local ATYPE = tonumber(
message:sub(answerSectionStarts + 5, answerSectionStarts + 8), 16)
local RDLENGTH = tonumber(
message:sub(answerSectionStarts + 21, answerSectionStarts + 24), 16)
local RDDATA = message:sub(
answerSectionStarts + 25, answerSectionStarts + 24 + (RDLENGTH * 2))
local RDDATA_decoded = ""
if #RDDATA > 0 then
if ATYPE == self:getQueryType("A") or ATYPE == self:getQueryType("AAAA") then
local octets = {}
local sep = "."
if #RDDATA > 8 then
sep = ":"
for i = 1, #RDDATA, 4 do
local string = RDDATA:sub(i, i + 3)
string = string:gsub("^00?0?", "")
octets[#octets + 1] = string
end
else
for i = 1, #RDDATA, 2 do
octets[#octets + 1] = tonumber(RDDATA:sub(i, i + 1), 16)
end
end
RDDATA_decoded = table.concat(octets, sep):gsub("0:[0:]+", "::", 1):gsub("::+", "::")
else
local rdata_t = {}
for _, v in ipairs(self:parseParts(RDDATA, 1, {})) do
local t = {}
for i = 1, #v, 2 do
t[#t + 1] = string.char(tonumber(v:sub(i, i + 1), 16))
end
rdata_t[#rdata_t + 1] = table.concat(t)
end
RDDATA_decoded = table.concat(rdata_t)
end
end
answerSectionStarts = answerSectionStarts + 24 + (RDLENGTH * 2)
if RDDATA_decoded:match("^[a-f0-9.:]+$") then
retTable[#retTable + 1] = RDDATA_decoded
end
end
end
end
return retTable
end
function Module:resolveIP()
local res
local fh = io.popen(self._nslookupCmd, "r")
if fh then
output = fh:read("*a")
fh:close()
if self._provider.name == "google" then
res = self:parseGoogle(output)
else
res = self:parseA(output)
local qtype = self._qtype and self._provider.queryType6 or self._provider.queryType
local server = self._qtype and self._provider.server6 or self._provider.server
local port = self._provider.port or self.port
if not self._DNSPacket then
self._DNSPacket = self:buildMessage(self._provider.host, qtype)
end
local retCode, response = self:sendUDPMessage(self._DNSPacket, server, port)
if retCode == 0 then
local retTable = self:decodeMessage(response)
if #retTable > 0 then
res = table.concat(retTable, ", ")
end
else
self.syslog("err", string.format(
"%s: Nslookup call failed (%s)", self.name, self.nslookup))
"%s: DNS error when requesting an IP address", self.name))
end
return res or "Undefined"
return res
end
function Module:init(t)
@@ -88,23 +331,11 @@ function Module:init(t)
else
self._provider = self.providers.opendns1
end
if not nixio.fs.access(self.nslookup, "x") then
self._enabled = false
self.syslog(
"warning",
string.format("%s: '%s' does not exists", self.name, self.nslookup)
)
else
self._enabled = true
self._nslookupCmd = string.format(
"%s -type=%s -timeout=%d %s %s",
self.nslookup,
self._provider.queryType,
self.timeout,
self._provider.host,
self._provider.server
)
end
self._qtype = (tonumber(t.qtype) ~= 0)
self._currentIp = nil
self._DNSPacket = nil
self._interval = self.runInterval
self._enabled = true
end
function Module:run(currentStatus, lastStatus, timeDiff)
@@ -112,8 +343,17 @@ function Module:run(currentStatus, lastStatus, timeDiff)
return
end
if currentStatus == 0 then
if self._counter == 0 or self._counter >= self.runInterval or currentStatus ~= lastStatus then
if self._counter == 0 or self._counter >= self._interval or currentStatus ~= lastStatus then
local ip = self:resolveIP()
if not ip then
ip = "Undefined"
self._interval = self.runIntervalFailed
else
self._interval = self.runInterval
end
if ip ~= self._currentIp then
self.status = ip
self.syslog(
@@ -123,6 +363,7 @@ function Module:run(currentStatus, lastStatus, timeDiff)
else
self.status = nil
end
self._currentIp = ip
self._counter = 0
else
@@ -132,7 +373,9 @@ function Module:run(currentStatus, lastStatus, timeDiff)
self.status = nil
self._currentIp = nil
self._counter = 0
self._interval = self.runInterval
end
self._counter = self._counter + timeDiff
end

View File

@@ -1,5 +1,5 @@
local nixio = require("nixio")
local unistd = require("posix.unistd")
local Module = {
name = "mod_reboot",
@@ -16,9 +16,8 @@ local Module = {
function Module:rebootDevice()
self.syslog("warning", string.format("%s: reboot", self.name))
os.execute("/sbin/reboot &")
if self.forceRebootDelay > 0 then
nixio.nanosleep(self.forceRebootDelay)
unistd.sleep(self.forceRebootDelay)
self.syslog("warning", string.format("%s: force reboot", self.name))
self.writeValue("/proc/sys/kernel/sysrq", "1")
self.writeValue("/proc/sysrq-trigger", "b")

View File

@@ -1,5 +1,5 @@
local nixio = require("nixio")
local unistd = require("posix.unistd")
local Module = {
name = "mod_user_scripts",
@@ -19,8 +19,8 @@ local Module = {
}
function Module:runExternalScript(scriptPath)
if nixio.fs.access(scriptPath, "x") then
os.execute(string.format('/bin/sh -c "%s" &', scriptPath))
if unistd.access(scriptPath, "r") then
os.execute(string.format('/bin/sh "%s" &', scriptPath))
end
end
@@ -28,8 +28,10 @@ function Module:init(t)
self.deadPeriod = tonumber(t.dead_period)
self.alivePeriod = tonumber(t.alive_period)
if self.config.configDir then
self.upScript = string.format("%s/up-script", self.config.configDir)
self.downScript = string.format("%s/down-script", self.config.configDir)
self.upScript = string.format(
"%s/up-script.%s", self.config.configDir, self.config.serviceConfig.instance)
self.downScript = string.format(
"%s/down-script.%s", self.config.configDir, self.config.serviceConfig.instance)
end
end
@@ -37,7 +39,6 @@ function Module:run(currentStatus, lastStatus, timeDiff)
if currentStatus == 1 then
self._aliveCounter = 0
self._downScriptExecuted = false
if not self._upScriptExecuted then
if self._deadCounter >= self.deadPeriod then
self:runExternalScript(self.downScript)
@@ -49,7 +50,6 @@ function Module:run(currentStatus, lastStatus, timeDiff)
else
self._deadCounter = 0
self._upScriptExecuted = false
if not self._downScriptExecuted then
if self._aliveCounter >= self.alivePeriod then
self:runExternalScript(self.upScript)