From 1e4cb26264f67b5fe8e3e55e17d1ad785c137f24 Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Sun, 22 Feb 2015 00:08:53 +0200 Subject: model: scattered lists --- aconf/model/node.lua | 47 +++++++++++++++++++++++++++++++++++++++------- aconf/modules/network.lua | 30 ++++++++++++++--------------- aconf/transaction/base.lua | 33 ++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 25 deletions(-) (limited to 'aconf') diff --git a/aconf/model/node.lua b/aconf/model/node.lua index 735e7df..d1e1037 100644 --- a/aconf/model/node.lua +++ b/aconf/model/node.lua @@ -33,15 +33,21 @@ M.BoundMember = class() function M.BoundMember:init(parent, name, field) local pmt = getmetatable(parent) - local addr = field.addr or address.escape(name) - if type(addr) == 'function' then addr = addr(pmt.path, name) end + if pmt.maddr and name ~= address.wildcard then self.addr = pmt.maddr(name) + else + self.addr = field.addr or address.escape(name) + if type(self.addr) == 'function' then + self.addr = self.addr(pmt.path, name) + end + self.addr = address.to_absolute(self.addr, pmt.addr) + end local context = { txn=pmt.txn, privileged=pmt.privileged, parent=parent, path=pth.join(pmt.path, name), - addr=address.to_absolute(addr, pmt.addr) + addr=self.addr } local mt = {} @@ -268,9 +274,9 @@ function M.Collection:init(context, params) self.init = nil local mt = getmetatable(self) - local field = M.BoundMember(self, pth.wildcard, params.field) + mt.field = M.BoundMember(self, pth.wildcard, params.field) - function mt.topology() return field:topology() end + function mt.topology() return mt.field:topology() end function mt.member(name) return M.BoundMember(self, name, params.field) @@ -287,7 +293,7 @@ function M.Collection:init(context, params) meta, { editable=params.editable and mt.has_permission('create'), - members=field:meta(), + members=mt.field:meta(), required=params.required, ['ui-member']=params.ui_member or meta['ui-name']:gsub('s$', ''), widget=params.layout @@ -364,8 +370,35 @@ function M.List:init(context, params) super(self, M.List):init(context, setdefaults(params, {dtype='list'})) local mt = getmetatable(self) - local tmt = getmetatable(mt.escalate) + if not mt.txn then return end + + local function expand() return mt.txn:expand(mt.field.addr) end + + function mt.maddr(i) + local addrs = expand() + + if not addrs[1] then + addrs[1] = address.join( + '/', + table.unpack( + util.map( + function(c) return c == address.wildcard and 1 or c end, + address.split(mt.field.addr) + ) + ) + ) + end + if addrs[i] then return addrs[i] end + + local comps = address.split(addrs[#addrs]) + comps[#comps] = comps[#comps] + i - #addrs + return address.join('/', table.unpack(comps)) + end + + function mt.members() return util.keys(expand()) end + + local tmt = getmetatable(mt.escalate) mt._save = mt.save local function check_index(i, max) diff --git a/aconf/modules/network.lua b/aconf/modules/network.lua index 82a83ef..8c985ff 100644 --- a/aconf/modules/network.lua +++ b/aconf/modules/network.lua @@ -92,12 +92,6 @@ end function Interface:is_removable() return self.class == 'logical' end -function Interface:auto_set() - for _, set in ipairs(self:fetch('../../enabled-ifaces')) do - if M.node.contains(set, self) then return set end - end -end - function Interface:auto_vlan_tag() local name = M.node.name(self) local _, tag = name:match(vlan_pattern) @@ -106,13 +100,14 @@ function Interface:auto_vlan_tag() end Interface.enabled = M.Boolean{ - compute=function(iface) return iface:auto_set() and true or false end, + compute=function(iface) + return M.node.contains(iface:fetch('../../enabled-ifaces'), iface) + end, store=function(iface, value) - local set = iface:auto_set() - if value and not set then - M.node.insert(iface:fetch('../../enabled-ifaces/1'), iface) - elseif not value and set then set[iface] = nil end - end + local set = iface:fetch('../../enabled-ifaces') + if value then M.node.insert(set, iface) + else set[iface] = nil end + end } Interface.class = M.String{ @@ -251,10 +246,13 @@ Net.resolver = M.Model{ model=Resolv, addr='/augeas/etc/resolv.conf', ui_name='DNS resolver' } -Net.enabled_ifaces = M.List{ - type=M.Set{type=M.Reference{scope='../../interfaces', on_delete='set-null'}}, - visible=false, - addr=iface_aug_addr..'/auto/#' +Net.enabled_ifaces = M.Set{ + type=M.Reference{ + scope='../interfaces', + addr=iface_aug_addr..'/auto/#/*/*', + on_delete='set-null' + }, + visible=false } Net.interfaces = M.Collection{ type=Interface, addr=iface_aug_addr..'/iface/@', widget='inline' diff --git a/aconf/transaction/base.lua b/aconf/transaction/base.lua index f40dcca..1886fd9 100644 --- a/aconf/transaction/base.lua +++ b/aconf/transaction/base.lua @@ -11,7 +11,7 @@ local object = require('aconf.object') local class = object.class local address = require('aconf.path.address') -local copy = require('aconf.util').copy +local util = require('aconf.util') -- TODO each transaction backend (i.e. persistence manager or -- transaction proper) should be implemented as a thread or have its @@ -107,7 +107,7 @@ function M.Transaction:get(path) if self.deleted[path] then return nil, self.mod_time[path] end for _, tbl in ipairs{self.added, self.modified} do if tbl[path] ~= nil then - return copy(tbl[path]), self.mod_time[path] + return util.copy(tbl[path]), self.mod_time[path] end end @@ -116,6 +116,35 @@ function M.Transaction:get(path) return value, timestamp end +function M.Transaction:expand(path) + local prefix = {} + path = address.split(path) + + while path[1] do + local comp = path[1] + table.remove(path, 1) + + if comp == address.wildcard then + local p = address.join('/', table.unpack(prefix)) + local res = {} + + local children = self:get(p) or {} + table.sort(children) + for _, child in ipairs(children) do + util.extend( + res, self:expand(address.join(p, child, table.unpack(path))) + ) + end + + return res + end + + table.insert(prefix, comp) + end + + return {address.join('/', table.unpack(prefix))} +end + function M.Transaction:_set_multiple(mods) local function set(path, value, new) -- cgit v1.2.3