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