PsychOSPackages/wgd/service/wgd.lua

169 lines
3.8 KiB
Lua
Raw Permalink Normal View History

2023-08-07 13:41:07 +10:00
local vcomponent = require "vcomponent"
local serial = require "serialization"
local rpc = require "rpc"
local wgd = {}
wgd.rescanTime = 60*5
wgd.allowTypes = {filesystem=true}
wgd.hosts = {}
wgd.components = {}
wgd.ignore = {computer.tmpAddress()}
local cImported = {}
local hostStat = {}
local function loadConfig()
local f = io.open("/boot/cfg/workgroup.cfg")
if not f then return false end
local cfg = serial.unserialize(f:read("*a"))
f:close()
for k,v in pairs(cfg) do
wgd[k] = v
end
end
local function saveConfig()
local wt = {
allowTypes=wgd.allowTypes,
hosts=wgd.hosts,
ignore=wgd.ignore,
rescanTime=wgd.rescanTime,
}
local f = io.open("/boot/cfg/workgroup.cfg","wb")
if not f then return false end
f:write(serial.serialize(wt))
f:close()
end
local function getComponents()
return wgd.components
end
local function exportComponent(a,norescan)
local p = component.proxy(a)
if p and wgd.allowTypes[p.type] and not cImported[a] and not wgd.ignore[a] then
for k,v in pairs(p) do
--[[
if type(v) == "function" or (type(v) == "table" and v.address == a and v.name == k) then
rpc.register(string.format("wg_%s_%s",a,k),v)
end
]]
rpc.register(string.format("wg_%s_%s",a,k),v)
wgd.components[a] = p.type
end
if norescan then return true end
for k,v in ipairs(wgd.hosts) do
rpc.call(v, "wg_rescan", os.getenv("HOSTNAME"))
end
end
end
local function unexportComponent(a)
if wgd.components[a] then
wgd.components[a] = nil
for k,v in ipairs(rpcf) do
if k:match("^wg_"..a:gsub("%-","%%-").."_") then
rpcf[k] = nil
end
end
for k,v in ipairs(hosts) do
rpc.call(v, "wg_rescan", os.getenv("HOSTNAME"))
end
end
end
local function hostUp(name,clist)
syslog("Host "..name.." is up, scanning components.")
for a,t in pairs(clist) do
syslog("Found "..a:sub(1,8).." ("..t..") on host "..name)
local px = rpc.proxy(name, "wg_"..a:gsub("%-","%%-").."_")
if type(px) == "table" then
if t == "filesystem" then
px.fstype = wg_mtfs
local olabel = px.getLabel
function px.getLabel()
local rl = olabel() or a:sub(1,3)
return string.format("/net/%s/%s",name,rl)
end
end
cImported[a] = name
vcomponent.register(a, t, px)
syslog("Attached "..a:sub(1,8).." ("..t..") on host "..name)
service.fsmanager.mount(a)
end
end
end
local function hostDown(name)
for ca,ha in pairs(cImported) do
if ha == name then
vcomponent.unregister(ca)
cImported[ca] = nil
end
end
end
function wgd.addHost(name)
wgd.removeHost(name)
wgd.hosts[#wgd.hosts+1] = name
saveConfig()
wgd.rescan(name)
end
function wgd.removeHost(name)
for i = #wgd.hosts, 1, -1 do
if wgd.hosts[i] == name then
print(table.remove(wgd.hosts, i))
end
end
saveConfig()
hostDown(name)
end
function wgd.rescan(name)
local targets = {name}
targets = #targets > 0 and targets or wgd.hosts
for _,n in ipairs(targets) do
os.spawn(function()
local clist = rpc.call(n, "wg_components")
if clist then
hostUp(n,clist)
else
hostDown(n)
end
end,"wgd worker: "..n)
coroutine.yield()
end
end
local run
function wgd.start()
if run then return end
run = true
return os.spawn(function()
loadConfig()
rpc.register("wg_components",getComponents)
rpc.register("wg_rescan",wgd.rescan)
local rst = computer.uptime() + 5
for a,t in component.list() do
exportComponent(a,true)
end
for k,v in ipairs(wgd.hosts) do
rpc.call(v, "wg_rescan", os.getenv("HOSTNAME"))
end
while run do
local tE = {coroutine.yield()}
if tE[1] == "component_added" then
exportComponent(tE[2])
elseif tE[1] == "component_removed" then
unexportComponent(tE[2])
end
if computer.uptime() > rst then
wgd.rescan()
rst = computer.uptime() + wgd.rescanTime
end
end
end, "workgroupd")
end
function wgd.stop()
run = false
end
return wgd