diff options
author | Jo-Philipp Wich <jo@mein.io> | 2018-05-18 16:44:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-18 16:44:33 +0200 |
commit | 828202ef5237f48e6f53d15ca198e2c6815b7cd7 (patch) | |
tree | a59276e5df1ebe77edca65b06b2a3b72f10ba70c /modules/luci-base/luasrc/model | |
parent | 80cb4fef8c7db0dadc373fef122d7abb092a7191 (diff) | |
parent | 9f796fad3a0cc89df57d4e27ef6d7223a093071c (diff) |
Merge pull request #1769 from jow-/master
UCI apply/rollback workflow
Diffstat (limited to 'modules/luci-base/luasrc/model')
-rw-r--r-- | modules/luci-base/luasrc/model/uci.lua | 139 | ||||
-rw-r--r-- | modules/luci-base/luasrc/model/uci.luadoc | 57 |
2 files changed, 127 insertions, 69 deletions
diff --git a/modules/luci-base/luasrc/model/uci.lua b/modules/luci-base/luasrc/model/uci.lua index fc2a605b3..34323f08b 100644 --- a/modules/luci-base/luasrc/model/uci.lua +++ b/modules/luci-base/luasrc/model/uci.lua @@ -3,6 +3,7 @@ local os = require "os" local util = require "luci.util" +local conf = require "luci.config" local table = require "table" @@ -143,22 +144,84 @@ function commit(self, 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 - call("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) @@ -425,59 +488,3 @@ function delete_all(self, config, stype, comparator) 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 diff --git a/modules/luci-base/luasrc/model/uci.luadoc b/modules/luci-base/luasrc/model/uci.luadoc index ef89d09b9..d798b0033 100644 --- a/modules/luci-base/luasrc/model/uci.luadoc +++ b/modules/luci-base/luasrc/model/uci.luadoc @@ -28,12 +28,63 @@ Create a new Cursor initialized to the state directory. ]] ---[[ -Applies UCI configuration changes +Applies UCI configuration changes. + +If the rollback parameter is set to true, the apply function will invoke the +rollback mechanism which causes the configuration to be automatically reverted +if no confirm() call occurs within a certain timeout. + +The current default timeout is 30s and can be increased using the +"luci.apply.timeout" uci configuration key. @class function @name Cursor.apply -@param configlist List of UCI configurations -@param command Don't apply only return the command +@param rollback Enable rollback mechanism +@return Boolean whether operation succeeded +]] + +---[[ +Confirms UCI apply process. + +If a previous UCI apply with rollback has been invoked using apply(true), +this function confirms the process and cancels the pending rollback timer. + +If no apply with rollback session is active, the function has no effect and +returns with a "No data" error. + +@class function +@name Cursor.confirm +@return Boolean whether operation succeeded +]] + +---[[ +Cancels UCI apply process. + +If a previous UCI apply with rollback has been invoked using apply(true), +this function cancels the process and rolls back the configuration to the +pre-apply state. + +If no apply with rollback session is active, the function has no effect and +returns with a "No data" error. + +@class function +@name Cursor.rollback +@return Boolean whether operation succeeded +]] + +---[[ +Checks whether a pending rollback is scheduled. + +If a previous UCI apply with rollback has been invoked using apply(true), +and has not been confirmed or rolled back yet, this function returns true +and the remaining time until rollback in seconds. If no rollback is pending, +the function returns false. On error, the function returns false and an +additional string describing the error. + +@class function +@name Cursor.rollback_pending +@return Boolean whether rollback is pending +@return Remaining time in seconds ]] ---[[ |