luci-app-mwan3: refactoring warning compilation on the interface config pages
[project/luci.git] / applications / luci-app-mwan3 / luasrc / model / cbi / mwan / interface.lua
1 dsp = require "luci.dispatcher"
2 sys = require "luci.sys"
3 ut = require "luci.util"
4
5 function interfaceWarnings(overview, count)
6         local warnings = ""
7         if count <= 250 then
8                 warnings = string.format("<strong>%s</strong></br>",
9                         translatef("There are currently %d of 250 supported interfaces configured", count)
10                         )
11         else
12                 warnings = string.format("<strong>%s</strong></br>",
13                         translatef("WARNING: %d interfaces are configured exceeding the maximum of 250!", count)
14                         )
15         end
16
17         for i, k in pairs(overview) do
18                 if overview[i]["network"] == false then
19                         warnings = warnings .. string.format("<strong>%s</strong></br>",
20                                         translatef("WARNING: Interface %s are not found in /etc/config/network", i)
21                                         )
22                 end
23
24                 if overview[i]["default_route"] == false then
25                         warnings = warnings .. string.format("<strong>%s</strong></br>",
26                                 translatef("WARNING: Interface %s has no default route in the main routing table", i)
27                                 )
28                 end
29
30                 if overview[i]["reliability"] == false then
31                         warnings = warnings .. string.format("<strong>%s</strong></br>",
32                                 translatef("WARNING: Interface %s has a higher reliability " ..
33                                 "requirement than tracking hosts (%d)", i, overview[i]["tracking"])
34                                 )
35                 end
36
37                 if overview[i]["duplicate_metric"] == true then
38                         warnings = warnings .. string.format("<strong>%s</strong></br>",
39                                 translatef("WARNING: Interface %s has a duplicate metric %s configured", i, overview[i]["metric"])
40                                 )
41                 end
42         end
43
44         return warnings
45 end
46
47 function configCheck()
48         local overview = {}
49         local count = 0
50         local duplicate_metric = {}
51         uci.cursor():foreach("mwan3", "interface",
52                 function (section)
53                         local uci = uci.cursor(nil, "/var/state")
54                         local iface = section[".name"]
55                         overview[iface] = {}
56                         count = count + 1
57                         local network = uci:get("network", iface)
58                         overview[iface]["network"] = false
59                         if network ~= nil then
60                                 overview[iface]["network"] = true
61
62                                 local device = uci:get("network", iface, "ifname")
63                                 if device ~= nil then
64                                         overview[iface]["device"] = device
65                                 end
66
67                                 local metric = uci:get("network", iface, "metric")
68                                 if metric ~= nil then
69                                         overview[iface]["metric"] = metric
70                                         overview[iface]["duplicate_metric"] = false
71                                         for _, m in ipairs(duplicate_metric) do
72                                                 if m == metric then
73                                                         overview[iface]["duplicate_metric"] = true
74                                                 end
75                                         end
76                                         table.insert(duplicate_metric, metric)
77                                 end
78
79                                 local dump = require("luci.util").ubus("network.interface.%s" % iface, "status", {})
80                                 overview[iface]["default_route"] = false
81                                 if dump then
82                                         local _, route
83                                         for _, route in ipairs(dump.route) do
84                                                 if dump.route[_].target == "0.0.0.0" then
85                                                         overview[iface]["default_route"] = true
86                                                 end
87                                         end
88                                 end
89                         end
90
91                         local trackingNumber = uci:get("mwan3", iface, "track_ip")
92                         overview[iface]["tracking"] = 0
93                         if #trackingNumber > 0 then
94                                 overview[iface]["tracking"] = #trackingNumber
95                                 overview[iface]["reliability"] = false
96                                 local reliabilityNumber = tonumber(uci:get("mwan3", iface, "reliability"))
97                                 if reliabilityNumber and reliabilityNumber <= #trackingNumber then
98                                         overview[iface]["reliability"] = true
99                                 end
100                         end
101                 end
102         )
103         return overview, count
104 end
105
106 m5 = Map("mwan3", translate("MWAN - Interfaces"),
107         interfaceWarnings(configCheck()))
108         m5:append(Template("mwan/config_css"))
109
110
111 mwan_interface = m5:section(TypedSection, "interface", nil,
112         translate("MWAN supports up to 250 physical and/or logical interfaces<br />" ..
113         "MWAN requires that all interfaces have a unique metric configured in /etc/config/network<br />" ..
114         "Names must match the interface name found in /etc/config/network (see advanced tab)<br />" ..
115         "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
116         "Interfaces may not share the same name as configured members, policies or rules"))
117         mwan_interface.addremove = true
118         mwan_interface.dynamic = false
119         mwan_interface.sectionhead = translate("Interface")
120         mwan_interface.sortable = false
121         mwan_interface.template = "cbi/tblsection"
122         mwan_interface.extedit = dsp.build_url("admin", "network", "mwan", "interface", "%s")
123         function mwan_interface.create(self, section)
124                 TypedSection.create(self, section)
125                 m5.uci:save("mwan3")
126                 luci.http.redirect(dsp.build_url("admin", "network", "mwan", "interface", section))
127         end
128
129
130 enabled = mwan_interface:option(DummyValue, "enabled", translate("Enabled"))
131         enabled.rawhtml = true
132         function enabled.cfgvalue(self, s)
133                 if self.map:get(s, "enabled") == "1" then
134                         return "Yes"
135                 else
136                         return "No"
137                 end
138         end
139
140 track_ip = mwan_interface:option(DummyValue, "track_ip", translate("Tracking IP"))
141         track_ip.rawhtml = true
142         function track_ip.cfgvalue(self, s)
143                 tracked = self.map:get(s, "track_ip")
144                 if tracked then
145                         local ipList = ""
146                         for k,v in pairs(tracked) do
147                                 ipList = ipList .. v .. "<br />"
148                         end
149                         return ipList
150                 else
151                         return "&#8212;"
152                 end
153         end
154
155 track_method = mwan_interface:option(DummyValue, "track_method", translate("Tracking method"))
156         track_method.rawhtml = true
157         function track_method.cfgvalue(self, s)
158                 if tracked then
159                         return self.map:get(s, "track_method") or "&#8212;"
160                 else
161                         return "&#8212;"
162                 end
163         end
164
165 reliability = mwan_interface:option(DummyValue, "reliability", translate("Tracking reliability"))
166         reliability.rawhtml = true
167         function reliability.cfgvalue(self, s)
168                 if tracked then
169                         return self.map:get(s, "reliability") or "&#8212;"
170                 else
171                         return "&#8212;"
172                 end
173         end
174
175 count = mwan_interface:option(DummyValue, "count", translate("Ping count"))
176         count.rawhtml = true
177         function count.cfgvalue(self, s)
178                 if tracked then
179                         return self.map:get(s, "count") or "&#8212;"
180                 else
181                         return "&#8212;"
182                 end
183         end
184
185 timeout = mwan_interface:option(DummyValue, "timeout", translate("Ping timeout"))
186         timeout.rawhtml = true
187         function timeout.cfgvalue(self, s)
188                 if tracked then
189                         local timeoutValue = self.map:get(s, "timeout")
190                         if timeoutValue then
191                                 return timeoutValue .. "s"
192                         else
193                                 return "&#8212;"
194                         end
195                 else
196                         return "&#8212;"
197                 end
198         end
199
200 interval = mwan_interface:option(DummyValue, "interval", translate("Ping interval"))
201         interval.rawhtml = true
202         function interval.cfgvalue(self, s)
203                 if tracked then
204                         local intervalValue = self.map:get(s, "interval")
205                         if intervalValue then
206                                 return intervalValue .. "s"
207                         else
208                                 return "&#8212;"
209                         end
210                 else
211                         return "&#8212;"
212                 end
213         end
214
215 down = mwan_interface:option(DummyValue, "down", translate("Interface down"))
216         down.rawhtml = true
217         function down.cfgvalue(self, s)
218                 if tracked then
219                         return self.map:get(s, "down") or "&#8212;"
220                 else
221                         return "&#8212;"
222                 end
223         end
224
225 up = mwan_interface:option(DummyValue, "up", translate("Interface up"))
226         up.rawhtml = true
227         function up.cfgvalue(self, s)
228                 if tracked then
229                         return self.map:get(s, "up") or "&#8212;"
230                 else
231                         return "&#8212;"
232                 end
233         end
234
235 metric = mwan_interface:option(DummyValue, "metric", translate("Metric"))
236         metric.rawhtml = true
237         function metric.cfgvalue(self, s)
238                 local metricValue = sys.exec("uci -p /var/state get network." .. s .. ".metric")
239                 if metricValue ~= "" then
240                         return metricValue
241                 else
242                         return "&#8212;"
243                 end
244         end
245
246 return m5