nlbw.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. -- Copyright 2017 Jo-Philipp Wich <jo@mein.io>
  2. -- Licensed to the public under the Apache License 2.0.
  3. module("luci.controller.nlbw", package.seeall)
  4. function index()
  5. entry({"admin", "nlbw"}, firstchild(), _("Bandwidth Monitor"), 80)
  6. entry({"admin", "nlbw", "display"}, template("nlbw/display"), _("Display"), 1)
  7. entry({"admin", "nlbw", "config"}, cbi("nlbw/config"), _("Configuration"), 2)
  8. entry({"admin", "nlbw", "backup"}, template("nlbw/backup"), _("Backup"), 3)
  9. entry({"admin", "nlbw", "data"}, call("action_data"), nil, 4)
  10. entry({"admin", "nlbw", "list"}, call("action_list"), nil, 5)
  11. entry({"admin", "nlbw", "ptr"}, call("action_ptr"), nil, 6).leaf = true
  12. entry({"admin", "nlbw", "download"}, call("action_download"), nil, 7)
  13. entry({"admin", "nlbw", "restore"}, post("action_restore"), nil, 8)
  14. entry({"admin", "nlbw", "commit"}, call("action_commit"), nil, 9)
  15. end
  16. local function exec(cmd, args, writer)
  17. local os = require "os"
  18. local nixio = require "nixio"
  19. local fdi, fdo = nixio.pipe()
  20. local pid = nixio.fork()
  21. if pid > 0 then
  22. fdo:close()
  23. while true do
  24. local buffer = fdi:read(2048)
  25. local wpid, stat, code = nixio.waitpid(pid, "nohang")
  26. if writer and buffer and #buffer > 0 then
  27. writer(buffer)
  28. end
  29. if wpid and stat == "exited" then
  30. break
  31. end
  32. end
  33. elseif pid == 0 then
  34. nixio.dup(fdo, nixio.stdout)
  35. fdi:close()
  36. fdo:close()
  37. nixio.exece(cmd, args, nil)
  38. nixio.stdout:close()
  39. os.exit(1)
  40. end
  41. end
  42. function action_data()
  43. local http = require "luci.http"
  44. local types = {
  45. csv = "text/csv",
  46. json = "application/json"
  47. }
  48. local args = { }
  49. local mtype = http.formvalue("type") or "json"
  50. local delim = http.formvalue("delim") or ";"
  51. local period = http.formvalue("period")
  52. local group_by = http.formvalue("group_by")
  53. local order_by = http.formvalue("order_by")
  54. if types[mtype] then
  55. args[#args+1] = "-c"
  56. args[#args+1] = mtype
  57. else
  58. http.status(400, "Unsupported type")
  59. return
  60. end
  61. if delim and #delim > 0 then
  62. args[#args+1] = "-s%s" % delim
  63. end
  64. if period and #period > 0 then
  65. args[#args+1] = "-t"
  66. args[#args+1] = period
  67. end
  68. if group_by and #group_by > 0 then
  69. args[#args+1] = "-g"
  70. args[#args+1] = group_by
  71. end
  72. if order_by and #order_by > 0 then
  73. args[#args+1] = "-o"
  74. args[#args+1] = order_by
  75. end
  76. http.prepare_content(types[mtype])
  77. exec("/usr/sbin/nlbw", args, http.write)
  78. end
  79. function action_list()
  80. local http = require "luci.http"
  81. local fd = io.popen("/usr/sbin/nlbw -c list")
  82. local periods = { }
  83. if fd then
  84. while true do
  85. local period = fd:read("*l")
  86. if not period then
  87. break
  88. end
  89. periods[#periods+1] = period
  90. end
  91. fd:close()
  92. end
  93. http.prepare_content("application/json")
  94. http.write_json(periods)
  95. end
  96. function action_ptr(...)
  97. local http = require "luci.http"
  98. local util = require "luci.util"
  99. http.prepare_content("application/json")
  100. http.write_json(util.ubus("network.rrdns", "lookup", {
  101. addrs = {...}, timeout = 3000
  102. }))
  103. end
  104. function action_download()
  105. local nixio = require "nixio"
  106. local http = require "luci.http"
  107. local sys = require "luci.sys"
  108. local uci = require "luci.model.uci".cursor()
  109. local dir = uci:get_first("nlbwmon", "nlbwmon", "database_directory")
  110. or "/var/lib/nlbwmon"
  111. if dir and nixio.fs.stat(dir, "type") == "dir" then
  112. local n = "nlbwmon-backup-%s-%s.tar.gz"
  113. %{ sys.hostname(), os.date("%Y-%m-%d") }
  114. http.prepare_content("application/octet-stream")
  115. http.header("Content-Disposition", "attachment; filename=\"%s\"" % n)
  116. exec("/bin/tar", { "-C", dir, "-c", "-z", ".", "-f", "-" }, http.write)
  117. else
  118. http.status(500, "Unable to find database directory")
  119. end
  120. end
  121. function action_restore()
  122. local nixio = require "nixio"
  123. local http = require "luci.http"
  124. local i18n = require "luci.i18n"
  125. local tpl = require "luci.template"
  126. local uci = require "luci.model.uci".cursor()
  127. local tmp = "/tmp/nlbw-restore.tar.gz"
  128. local dir = uci:get_first("nlbwmon", "nlbwmon", "database_directory")
  129. or "/var/lib/nlbwmon"
  130. local fp
  131. http.setfilehandler(
  132. function(meta, chunk, eof)
  133. if not fp and meta and meta.name == "archive" then
  134. fp = io.open(tmp, "w")
  135. end
  136. if fp and chunk then
  137. fp:write(chunk)
  138. end
  139. if fp and eof then
  140. fp:close()
  141. end
  142. end)
  143. local files = { }
  144. local tar = io.popen("/bin/tar -tzf %s" % tmp, "r")
  145. if tar then
  146. while true do
  147. local file = tar:read("*l")
  148. if not file then
  149. break
  150. elseif file:match("^%d%d%d%d%d%d%d%d%.db%.gz$") or
  151. file:match("^%./%d%d%d%d%d%d%d%d%.db%.gz$") then
  152. files[#files+1] = file
  153. end
  154. end
  155. tar:close()
  156. end
  157. if #files == 0 then
  158. http.status(500, "Internal Server Error")
  159. tpl.render("nlbw/backup", {
  160. message = i18n.translate("Invalid or empty backup archive")
  161. })
  162. return
  163. end
  164. local output = { }
  165. exec("/etc/init.d/nlbwmon", { "stop" })
  166. exec("/bin/mkdir", { "-p", dir })
  167. exec("/bin/tar", { "-C", dir, "-vxzf", tmp, unpack(files) },
  168. function(chunk) output[#output+1] = chunk:match("%S+") end)
  169. exec("/bin/rm", { "-f", tmp })
  170. exec("/etc/init.d/nlbwmon", { "start" })
  171. tpl.render("nlbw/backup", {
  172. message = i18n.translatef(
  173. "The following database files have been restored: %s",
  174. table.concat(output, ", "))
  175. })
  176. end
  177. function action_commit()
  178. local http = require "luci.http"
  179. local disp = require "luci.dispatcher"
  180. http.redirect(disp.build_url("admin/nlbw/display"))
  181. exec("/usr/sbin/nlbw", { "-c", "commit" })
  182. end