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