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