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