luci-app-mwan3: move/rename hotplugscript tab
[project/luci.git] / applications / luci-app-mwan3 / luasrc / controller / mwan3.lua
1 module("luci.controller.mwan3", package.seeall)
2
3 sys = require "luci.sys"
4 ut = require "luci.util"
5
6 ip = "ip -4 "
7
8 function index()
9 if not nixio.fs.access("/etc/config/mwan3") then
10 return
11 end
12
13 entry({"admin", "network", "mwan"},
14 alias("admin", "network", "mwan", "overview"),
15 _("Load Balancing"), 600)
16
17 entry({"admin", "network", "mwan", "overview"},
18 alias("admin", "network", "mwan", "overview", "overview_interface"),
19 _("Overview"), 10)
20 entry({"admin", "network", "mwan", "overview", "overview_interface"},
21 template("mwan/overview_interface"))
22 entry({"admin", "network", "mwan", "overview", "interface_status"},
23 call("interfaceStatus"))
24 entry({"admin", "network", "mwan", "overview", "overview_detailed"},
25 template("mwan/overview_detailed"))
26 entry({"admin", "network", "mwan", "overview", "detailed_status"},
27 call("detailedStatus"))
28
29 entry({"admin", "network", "mwan", "configuration"},
30 alias("admin", "network", "mwan", "configuration", "interface"),
31 _("Configuration"), 20)
32 entry({"admin", "network", "mwan", "configuration", "globals"},
33 cbi("mwan/globalsconfig"),_("Globals"), 5).leaf = true
34 entry({"admin", "network", "mwan", "configuration", "interface"},
35 arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
36 _("Interfaces"), 10).leaf = true
37 entry({"admin", "network", "mwan", "configuration", "member"},
38 arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
39 _("Members"), 20).leaf = true
40 entry({"admin", "network", "mwan", "configuration", "policy"},
41 arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
42 _("Policies"), 30).leaf = true
43 entry({"admin", "network", "mwan", "configuration", "rule"},
44 arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
45 _("Rules"), 40).leaf = true
46 entry({"admin", "network", "mwan", "configuration", "notify"},
47 cbi("mwan/notify"),
48 _("Notification"), 50).leaf = true
49
50 entry({"admin", "network", "mwan", "advanced"},
51 alias("admin", "network", "mwan", "advanced", "mwanconfig"),
52 _("Advanced"), 100)
53 entry({"admin", "network", "mwan", "advanced", "mwanconfig"},
54 form("mwan/advanced_mwanconfig"))
55 entry({"admin", "network", "mwan", "advanced", "networkconfig"},
56 form("mwan/advanced_networkconfig"))
57 entry({"admin", "network", "mwan", "advanced", "wirelessconfig"},
58 form("mwan/advanced_wirelessconfig"))
59 entry({"admin", "network", "mwan", "advanced", "diagnostics"},
60 template("mwan/advanced_diagnostics"))
61 entry({"admin", "network", "mwan", "advanced", "diagnostics_display"},
62 call("diagnosticsData"), nil).leaf = true
63 entry({"admin", "network", "mwan", "advanced", "troubleshooting"},
64 template("mwan/advanced_troubleshooting"))
65 entry({"admin", "network", "mwan", "advanced", "troubleshooting_display"},
66 call("troubleshootingData"))
67 end
68
69 function getInterfaceStatus(ruleNumber, interfaceName)
70 if ut.trim(sys.exec("uci -q -p /var/state get mwan3." .. interfaceName .. ".enabled")) == "1" then
71 if ut.trim(sys.exec(ip .. "route list table " .. ruleNumber)) ~= "" then
72 if ut.trim(sys.exec("uci -q -p /var/state get mwan3." .. interfaceName .. ".track_ip")) ~= "" then
73 return "online"
74 else
75 return "notMonitored"
76 end
77 else
78 return "offline"
79 end
80 else
81 return "notEnabled"
82 end
83 end
84
85 function getInterfaceName()
86 local ruleNumber, status = 0, ""
87 uci.cursor():foreach("mwan3", "interface",
88 function (section)
89 ruleNumber = ruleNumber+1
90 status = status .. section[".name"] .. "[" .. getInterfaceStatus(ruleNumber, section[".name"]) .. "]"
91 end
92 )
93 return status
94 end
95
96 function interfaceStatus()
97 local ntm = require "luci.model.network".init()
98
99 local mArray = {}
100
101 -- overview status
102 local statusString = getInterfaceName()
103 if statusString ~= "" then
104 mArray.wans = {}
105 wansid = {}
106
107 for wanName, interfaceState in string.gfind(statusString, "([^%[]+)%[([^%]]+)%]") do
108 local wanInterfaceName = ut.trim(sys.exec("uci -q -p /var/state get network." .. wanName .. ".ifname"))
109 if wanInterfaceName == "" then
110 wanInterfaceName = "X"
111 end
112 local wanDeviceLink = ntm:get_interface(wanInterfaceName)
113 wanDeviceLink = wanDeviceLink and wanDeviceLink:get_network()
114 wanDeviceLink = wanDeviceLink and wanDeviceLink:adminlink() or "#"
115 wansid[wanName] = #mArray.wans + 1
116 mArray.wans[wansid[wanName]] = { name = wanName, link = wanDeviceLink, ifname = wanInterfaceName, status = interfaceState }
117 end
118 end
119
120 -- overview status log
121 local mwanLog = ut.trim(sys.exec("logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x' 2>/dev/null"))
122 if mwanLog ~= "" then
123 mArray.mwanlog = { mwanLog }
124 end
125
126 luci.http.prepare_content("application/json")
127 luci.http.write_json(mArray)
128 end
129
130 function detailedStatus()
131 local mArray = {}
132
133 -- detailed mwan status
134 local detailStatusInfo = ut.trim(sys.exec("/usr/sbin/mwan3 status"))
135 if detailStatusInfo ~= "" then
136 mArray.mwandetail = { detailStatusInfo }
137 end
138
139 luci.http.prepare_content("application/json")
140 luci.http.write_json(mArray)
141 end
142
143 function diagnosticsData(interface, tool, task)
144 function getInterfaceNumber()
145 local number = 0
146 uci.cursor():foreach("mwan3", "interface",
147 function (section)
148 number = number+1
149 if section[".name"] == interface then
150 interfaceNumber = number
151 end
152 end
153 )
154 end
155
156 local mArray = {}
157
158 local results = ""
159 if tool == "service" then
160 os.execute("/usr/sbin/mwan3 " .. task)
161 if task == "restart" then
162 results = "MWAN3 restarted"
163 elseif task == "stop" then
164 results = "MWAN3 stopped"
165 else
166 results = "MWAN3 started"
167 end
168 else
169 local interfaceDevice = ut.trim(sys.exec("uci -q -p /var/state get network." .. interface .. ".ifname"))
170 if interfaceDevice ~= "" then
171 if tool == "ping" then
172 local gateway = ut.trim(sys.exec("route -n | awk '{if ($8 == \"" .. interfaceDevice .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $2}'"))
173 if gateway ~= "" then
174 if task == "gateway" then
175 local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. gateway
176 results = pingCommand .. "\n\n" .. sys.exec(pingCommand)
177 else
178 local tracked = ut.trim(sys.exec("uci -q -p /var/state get mwan3." .. interface .. ".track_ip"))
179 if tracked ~= "" then
180 for z in tracked:gmatch("[^ ]+") do
181 local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. z
182 results = results .. pingCommand .. "\n\n" .. sys.exec(pingCommand) .. "\n\n"
183 end
184 else
185 results = "No tracking IP addresses configured on " .. interface
186 end
187 end
188 else
189 results = "No default gateway for " .. interface .. " found. Default route does not exist or is configured incorrectly"
190 end
191 elseif tool == "rulechk" then
192 getInterfaceNumber()
193 local rule1 = sys.exec(ip .. "rule | grep $(echo $((" .. interfaceNumber .. " + 1000)))")
194 local rule2 = sys.exec(ip .. "rule | grep $(echo $((" .. interfaceNumber .. " + 2000)))")
195 if rule1 ~= "" and rule2 ~= "" then
196 results = "All required interface IP rules found:\n\n" .. rule1 .. rule2
197 elseif rule1 ~= "" or rule2 ~= "" then
198 results = "Missing 1 of the 2 required interface IP rules\n\n\nRules found:\n\n" .. rule1 .. rule2
199 else
200 results = "Missing both of the required interface IP rules"
201 end
202 elseif tool == "routechk" then
203 getInterfaceNumber()
204 local routeTable = sys.exec(ip .. "route list table " .. interfaceNumber)
205 if routeTable ~= "" then
206 results = "Interface routing table " .. interfaceNumber .. " was found:\n\n" .. routeTable
207 else
208 results = "Missing required interface routing table " .. interfaceNumber
209 end
210 elseif tool == "hotplug" then
211 if task == "ifup" then
212 os.execute("/usr/sbin/mwan3 ifup " .. interface)
213 results = "Hotplug ifup sent to interface " .. interface .. "..."
214 else
215 os.execute("/usr/sbin/mwan3 ifdown " .. interface)
216 results = "Hotplug ifdown sent to interface " .. interface .. "..."
217 end
218 end
219 else
220 results = "Unable to perform diagnostic tests on " .. interface .. ". There is no physical or virtual device associated with this interface"
221 end
222 end
223 if results ~= "" then
224 results = ut.trim(results)
225 mArray.diagnostics = { results }
226 end
227
228 luci.http.prepare_content("application/json")
229 luci.http.write_json(mArray)
230 end
231
232 function troubleshootingData()
233 local ver = require "luci.version"
234
235 local mArray = {}
236
237 -- software versions
238 local wrtRelease = ut.trim(ver.distversion)
239 if wrtRelease ~= "" then
240 wrtRelease = "OpenWrt - " .. wrtRelease
241 else
242 wrtRelease = "OpenWrt - unknown"
243 end
244 local luciRelease = ut.trim(ver.luciversion)
245 if luciRelease ~= "" then
246 luciRelease = "\nLuCI - " .. luciRelease
247 else
248 luciRelease = "\nLuCI - unknown"
249 end
250 local mwanVersion = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk '{print $2}'"))
251 if mwanVersion ~= "" then
252 mwanVersion = "\n\nmwan3 - " .. mwanVersion
253 else
254 mwanVersion = "\n\nmwan3 - unknown"
255 end
256 local mwanLuciVersion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk '{print $2}'"))
257 if mwanLuciVersion ~= "" then
258 mwanLuciVersion = "\nmwan3-luci - " .. mwanLuciVersion
259 else
260 mwanLuciVersion = "\nmwan3-luci - unknown"
261 end
262 mArray.versions = { wrtRelease .. luciRelease .. mwanVersion .. mwanLuciVersion }
263
264 -- mwan config
265 local mwanConfig = ut.trim(sys.exec("cat /etc/config/mwan3"))
266 if mwanConfig == "" then
267 mwanConfig = "No data found"
268 end
269 mArray.mwanconfig = { mwanConfig }
270
271 -- network config
272 local networkConfig = ut.trim(sys.exec("cat /etc/config/network | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/'"))
273 if networkConfig == "" then
274 networkConfig = "No data found"
275 end
276 mArray.netconfig = { networkConfig }
277
278 -- wireless config
279 local wirelessConfig = ut.trim(sys.exec("cat /etc/config/wireless | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/' -e 's/.*key.*/ KEY HIDDEN/'"))
280 if wirelessConfig == "" then
281 wirelessConfig = "No data found"
282 end
283 mArray.wificonfig = { wirelessConfig }
284
285 -- ifconfig
286 local ifconfig = ut.trim(sys.exec("ifconfig"))
287 if ifconfig == "" then
288 ifconfig = "No data found"
289 end
290 mArray.ifconfig = { ifconfig }
291
292 -- route -n
293 local routeShow = ut.trim(sys.exec("route -n"))
294 if routeShow == "" then
295 routeShow = "No data found"
296 end
297 mArray.routeshow = { routeShow }
298
299 -- ip rule show
300 local ipRuleShow = ut.trim(sys.exec(ip .. "rule show"))
301 if ipRuleShow == "" then
302 ipRuleShow = "No data found"
303 end
304 mArray.iprule = { ipRuleShow }
305
306 -- ip route list table 1-250
307 local routeList, routeString = ut.trim(sys.exec(ip .. "rule | sed 's/://g' 2>/dev/null | awk '$1>=2001 && $1<=2250' | awk '{print $NF}'")), ""
308 if routeList ~= "" then
309 for line in routeList:gmatch("[^\r\n]+") do
310 routeString = routeString .. line .. "\n" .. sys.exec(ip .. "route list table " .. line)
311 end
312 routeString = ut.trim(routeString)
313 else
314 routeString = "No data found"
315 end
316 mArray.routelist = { routeString }
317
318 -- default firewall output policy
319 local firewallOut = ut.trim(sys.exec("uci -q -p /var/state get firewall.@defaults[0].output"))
320 if firewallOut == "" then
321 firewallOut = "No data found"
322 end
323 mArray.firewallout = { firewallOut }
324
325 -- iptables
326 local iptables = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
327 if iptables == "" then
328 iptables = "No data found"
329 end
330 mArray.iptables = { iptables }
331
332 luci.http.prepare_content("application/json")
333 luci.http.write_json(mArray)
334 end