-- Copyright 2017 Jo-Philipp Wich -- Licensed to the public under the Apache License 2.0. module("luci.controller.nlbw", package.seeall) function index() entry({"admin", "nlbw"}, firstchild(), _("Bandwidth Monitor"), 80) entry({"admin", "nlbw", "display"}, template("nlbw/display"), _("Display"), 1) entry({"admin", "nlbw", "config"}, cbi("nlbw/config"), _("Configuration"), 2) entry({"admin", "nlbw", "backup"}, template("nlbw/backup"), _("Backup"), 3) entry({"admin", "nlbw", "data"}, call("action_data"), nil, 4) entry({"admin", "nlbw", "list"}, call("action_list"), nil, 5) entry({"admin", "nlbw", "ptr"}, call("action_ptr"), nil, 6).leaf = true entry({"admin", "nlbw", "download"}, call("action_download"), nil, 7) entry({"admin", "nlbw", "restore"}, post("action_restore"), nil, 8) entry({"admin", "nlbw", "commit"}, call("action_commit"), nil, 9) end local function exec(cmd, args, writer) local os = require "os" local nixio = require "nixio" local fdi, fdo = nixio.pipe() local pid = nixio.fork() if pid > 0 then fdo:close() while true do local buffer = fdi:read(2048) local wpid, stat, code = nixio.waitpid(pid, "nohang") if writer and buffer and #buffer > 0 then writer(buffer) end if wpid and stat == "exited" then break end end elseif pid == 0 then nixio.dup(fdo, nixio.stdout) fdi:close() fdo:close() nixio.exece(cmd, args, nil) nixio.stdout:close() os.exit(1) end end function action_data() local http = require "luci.http" local types = { csv = "text/csv", json = "application/json" } local args = { } local mtype = http.formvalue("type") or "json" local delim = http.formvalue("delim") or ";" local period = http.formvalue("period") local group_by = http.formvalue("group_by") local order_by = http.formvalue("order_by") if types[mtype] then args[#args+1] = "-c" args[#args+1] = mtype else http.status(400, "Unsupported type") return end if delim and #delim > 0 then args[#args+1] = "-s%s" % delim end if period and #period > 0 then args[#args+1] = "-t" args[#args+1] = period end if group_by and #group_by > 0 then args[#args+1] = "-g" args[#args+1] = group_by end if order_by and #order_by > 0 then args[#args+1] = "-o" args[#args+1] = order_by end http.prepare_content(types[mtype]) exec("/usr/sbin/nlbw", args, http.write) end function action_list() local http = require "luci.http" local fd = io.popen("/usr/sbin/nlbw -c list") local periods = { } if fd then while true do local period = fd:read("*l") if not period then break end periods[#periods+1] = period end fd:close() end http.prepare_content("application/json") http.write_json(periods) end function action_ptr(...) local http = require "luci.http" local util = require "luci.util" http.prepare_content("application/json") http.write_json(util.ubus("network.rrdns", "lookup", { addrs = {...}, timeout = 3000 })) end function action_download() local nixio = require "nixio" local http = require "luci.http" local sys = require "luci.sys" local uci = require "luci.model.uci".cursor() local dir = uci:get_first("nlbwmon", "nlbwmon", "database_directory") or "/var/lib/nlbwmon" if dir and nixio.fs.stat(dir, "type") == "dir" then local n = "nlbwmon-backup-%s-%s.tar.gz" %{ sys.hostname(), os.date("%Y-%m-%d") } http.prepare_content("application/octet-stream") http.header("Content-Disposition", "attachment; filename=\"%s\"" % n) exec("/bin/tar", { "-C", dir, "-c", "-z", ".", "-f", "-" }, http.write) else http.status(500, "Unable to find database directory") end end function action_restore() local nixio = require "nixio" local http = require "luci.http" local i18n = require "luci.i18n" local tpl = require "luci.template" local uci = require "luci.model.uci".cursor() local tmp = "/tmp/nlbw-restore.tar.gz" local dir = uci:get_first("nlbwmon", "nlbwmon", "database_directory") or "/var/lib/nlbwmon" local fp http.setfilehandler( function(meta, chunk, eof) if not fp and meta and meta.name == "archive" then fp = io.open(tmp, "w") end if fp and chunk then fp:write(chunk) end if fp and eof then fp:close() end end) local files = { } local tar = io.popen("/bin/tar -tzf %s" % tmp, "r") if tar then while true do local file = tar:read("*l") if not file then break elseif file:match("^%d%d%d%d%d%d%d%d%.db%.gz$") or file:match("^%./%d%d%d%d%d%d%d%d%.db%.gz$") then files[#files+1] = file end end tar:close() end if #files == 0 then http.status(500, "Internal Server Error") tpl.render("nlbw/backup", { message = i18n.translate("Invalid or empty backup archive") }) return end local output = { } exec("/etc/init.d/nlbwmon", { "stop" }) exec("/bin/mkdir", { "-p", dir }) exec("/bin/tar", { "-C", dir, "-vxzf", tmp, unpack(files) }, function(chunk) output[#output+1] = chunk:match("%S+") end) exec("/bin/rm", { "-f", tmp }) exec("/etc/init.d/nlbwmon", { "start" }) tpl.render("nlbw/backup", { message = i18n.translatef( "The following database files have been restored: %s", table.concat(output, ", ")) }) end function action_commit() local http = require "luci.http" local disp = require "luci.dispatcher" http.redirect(disp.build_url("admin/nlbw/display")) exec("/usr/sbin/nlbw", { "-c", "commit" }) end