diff options
Diffstat (limited to 'app/service-model.lua')
-rw-r--r-- | app/service-model.lua | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/app/service-model.lua b/app/service-model.lua new file mode 100644 index 0000000..d6fb192 --- /dev/null +++ b/app/service-model.lua @@ -0,0 +1,122 @@ +module (..., package.seeall) + +require "fs" + + +--TODO this should be somehow figureoutable from acf info, help! +local cfgdir = "/usr/share/acf/app/service" + +--TODO, in fs actually, find should use coroutines instead of reading +--all in table + +local spec = nil + +--TODO might on demand load only part of config that is needed for this app +--but then TODO need to make persistent item ids +local function loadCfg() + if spec ~= nil then return end + spec = {} + for fname in fs.find(".*%.srv", cfgdir) do + f = io.open(fname, 'r') + if f then + s = f:read("*a") + f:close() + if s then + c = loadstring("return ({\n" .. s .. "\n})") + if c then + for i,v in ipairs(c()) do + spec[#spec + 1] = v + end + end + end + end + end +end + + + +local function getAnyPid(pname) + for e in lfs.dir("/proc") do + if e == string.match(e, "^%d*$") then + for line in io.lines("/proc/" .. e .. "/status") do + tag, val = string.match(line, "^([^:]*):%s*(%S*)$"); + if tag == "Name" then + if val == pname then return e end + break + end + end + end + end +end + +local mech = {} + +function mech.initd(service, action) + if not service.initd then return false, "no initd" end + local f = io.popen("/etc/init.d/" .. service.initd .. ' ' .. action, "r") + if not f then return false, "cannot run initd" end + local ret = f:read("*a") + f:close() + return true, ret +end + +function mech.pidfile(svc, action) + if not service.pidfile then return false end + if action ~= "status" then return false end + f = io.open(svc.pidfile) + if not f then return true, false end + pid = tonumber(f:read("*a")) + f:close() + if not pid then return true, false end + f = io.open("/proc/" .. tostring(pid) .. "/status") + if not f then return true, false end + if svc.pidcmdname then + for line in f:lines() do + k, v = string.match(line, '^([^:]*):%s*(.*)$') + if k == "Name" then + return true, (v == svc.pidcmdname) + end + end + end + f:close() + return true, true +end + +local function serviceAction(service, action) + if not service[action] then return false, "no such action " .. action end + return mech[service[action]](service, action) +end + +local function getServiceActions(service) + local ret = {} + if service.start then ret[#ret + 1] = "start" end + if service.stop then ret[#ret + 1] = "stop" end + if service.restart then ret[#ret + 1] = "restart" end + if service.reload then ret[#ret + 1] = "reload" end + return ret +end + +function list(self, app) + loadCfg() + ret = {} + for k,v in pairs(spec) do + if v.app == app then + ret[#ret+1] = { + id=k, + name=v.name, + descr=v.descr or "", + status=serviceAction(v, "status"), + actions=getServiceActions(v) + } + end + end + return ret +end + +function update(self, id, action) + loadCfg() + svc = spec[id] + if not svc then return false, "no service" end + return serviceAction(svc, action) +end + |