local os = require "os"
local util = require "luci.util"
+local conf = require "luci.config"
local table = require "table"
"Connection failed"
}
+local session_id = nil
+
+local function call(cmd, args)
+ if type(args) == "table" and session_id then
+ args.ubus_rpc_session = session_id
+ end
+ return util.ubus("uci", cmd, args)
+end
+
function cursor()
return _M
return "/tmp/.uci"
end
+function get_session_id(self)
+ return session_id
+end
+
function set_confdir(self, directory)
return false
end
return false
end
+function set_session_id(self, id)
+ session_id = id
+ return true
+end
+
function load(self, config)
return true
function changes(self, config)
- local rv = util.ubus("uci", "changes", { config = config })
+ local rv = call("changes", { config = config })
local res = {}
if type(rv) == "table" and type(rv.changes) == "table" then
function revert(self, config)
- local _, err = util.ubus("uci", "revert", { config = config })
+ local _, err = call("revert", { config = config })
return (err == nil), ERRSTR[err]
end
function commit(self, config)
- local _, err = util.ubus("uci", "commit", { config = config })
+ local _, err = call("commit", { config = config })
return (err == nil), ERRSTR[err]
end
---[[
-function apply(self, configs, command)
- local _, config
+function apply(self, rollback)
+ local _, err
+
+ if rollback then
+ local timeout = tonumber(conf.apply and conf.apply.rollback or "") or 0
- assert(not command, "Apply command not supported anymore")
+ _, err = call("apply", {
+ timeout = (timeout > 30) and timeout or 30,
+ rollback = true
+ })
- if type(configs) == "table" then
- for _, config in ipairs(configs) do
- util.ubus("service", "event", {
- type = "config.change",
- data = { package = config }
+ if not err then
+ util.ubus("session", "set", {
+ ubus_rpc_session = session_id,
+ values = { rollback = os.time() + timeout }
})
end
+ else
+ _, err = call("changes", {})
+
+ if not err then
+ if type(_) == "table" and type(_.changes) == "table" then
+ local k, v
+ for k, v in pairs(_.changes) do
+ _, err = call("commit", { config = k })
+ if err then
+ break
+ end
+ end
+ end
+ end
+
+ if not err then
+ _, err = call("apply", { rollback = false })
+ end
+ end
+
+ return (err == nil), ERRSTR[err]
+end
+
+function confirm(self)
+ local _, err = call("confirm", {})
+ if not err then
+ util.ubus("session", "set", {
+ ubus_rpc_session = session_id,
+ values = { rollback = 0 }
+ })
+ end
+ return (err == nil), ERRSTR[err]
+end
+
+function rollback(self)
+ local _, err = call("rollback", {})
+ if not err then
+ util.ubus("session", "set", {
+ ubus_rpc_session = session_id,
+ values = { rollback = 0 }
+ })
end
+ return (err == nil), ERRSTR[err]
+end
+
+function rollback_pending(self)
+ local deadline, err = util.ubus("session", "get", {
+ ubus_rpc_session = session_id,
+ keys = { "rollback" }
+ })
+
+ if type(deadline) == "table" and
+ type(deadline.values) == "table" and
+ type(deadline.values.rollback) == "number" and
+ deadline.values.rollback > os.time()
+ then
+ return true, deadline.values.rollback - os.time()
+ end
+
+ return false, ERRSTR[err]
end
-]]
function foreach(self, config, stype, callback)
if type(callback) == "function" then
- local rv, err = util.ubus("uci", "get", {
+ local rv, err = call("get", {
config = config,
type = stype
})
if section == nil then
return nil
elseif type(option) == "string" and option:byte(1) ~= 46 then
- local rv, err = util.ubus("uci", operation, {
+ local rv, err = call(operation, {
config = config,
section = section,
option = option
end
function get_all(self, config, section)
- local rv, err = util.ubus("uci", "get", {
+ local rv, err = call("get", {
config = config,
section = section
})
function section(self, config, stype, name, values)
- local rv, err = util.ubus("uci", "add", {
+ local rv, err = call("add", {
config = config,
type = stype,
name = name,
local sname, err = self:section(config, option, section)
return (not not sname), err
else
- local _, err = util.ubus("uci", "set", {
+ local _, err = call("set", {
config = config,
section = section,
values = { [option] = value }
end
function tset(self, config, section, values)
- local _, err = util.ubus("uci", "set", {
+ local _, err = call("set", {
config = config,
section = section,
values = values
return false, "Invalid argument"
end
- local _, err = util.ubus("uci", "order", {
+ local _, err = call("order", {
config = config,
sections = sections
})
function delete(self, config, section, option)
- local _, err = util.ubus("uci", "delete", {
+ local _, err = call("delete", {
config = config,
section = section,
option = option
function delete_all(self, config, stype, comparator)
local _, err
if type(comparator) == "table" then
- _, err = util.ubus("uci", "delete", {
+ _, err = call("delete", {
config = config,
type = stype,
match = comparator
})
elseif type(comparator) == "function" then
- local rv = util.ubus("uci", "get", {
+ local rv = call("get", {
config = config,
type = stype
})
local sname, section
for sname, section in pairs(rv.values) do
if comparator(section) then
- _, err = util.ubus("uci", "delete", {
+ _, err = call("delete", {
config = config,
section = sname
})
end
end
elseif comparator == nil then
- _, err = util.ubus("uci", "delete", {
+ _, err = call("delete", {
config = config,
type = stype
})
return (err == nil), ERRSTR[err]
end
-
-
-function apply(self, configlist, command)
- configlist = self:_affected(configlist)
- if command then
- return { "/sbin/luci-reload", unpack(configlist) }
- else
- return os.execute("/sbin/luci-reload %s >/dev/null 2>&1"
- % util.shellquote(table.concat(configlist, " ")))
- end
-end
-
--- Return a list of initscripts affected by configuration changes.
-function _affected(self, configlist)
- configlist = type(configlist) == "table" and configlist or { configlist }
-
- -- Resolve dependencies
- local reloadlist = { }
-
- local function _resolve_deps(name)
- local reload = { name }
- local deps = { }
-
- self:foreach("ucitrack", name,
- function(section)
- if section.affects then
- for i, aff in ipairs(section.affects) do
- deps[#deps+1] = aff
- end
- end
- end)
-
- local i, dep
- for i, dep in ipairs(deps) do
- local j, add
- for j, add in ipairs(_resolve_deps(dep)) do
- reload[#reload+1] = add
- end
- end
-
- return reload
- end
-
- -- Collect initscripts
- local j, config
- for j, config in ipairs(configlist) do
- local i, e
- for i, e in ipairs(_resolve_deps(config)) do
- if not util.contains(reloadlist, e) then
- reloadlist[#reloadlist+1] = e
- end
- end
- end
-
- return reloadlist
-end