summaryrefslogtreecommitdiffstats
path: root/app/service-model.lua
diff options
context:
space:
mode:
Diffstat (limited to 'app/service-model.lua')
-rw-r--r--app/service-model.lua122
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
+