luci-app-nlbwmon: new package
[project/luci.git] / applications / luci-app-nlbwmon / luasrc / model / cbi / nlbw / config.lua
1 -- Copyright 2017 Jo-Philipp Wich <jo@mein.io>
2 -- Licensed to the public under the Apache License 2.0.
3
4 local utl = require "luci.util"
5 local sys = require "luci.sys"
6 local fs  = require "nixio.fs"
7 local ip  = require "luci.ip"
8 local nw  = require "luci.model.network"
9
10 local s, m, period, warning, date, days, interval, ifaces, subnets, limit, prealloc, compress, generations, commit, refresh, directory, protocols
11
12 m = Map("nlbwmon", translate("Netlink Bandwidth Monitor - Configuration"),
13         translate("The Netlink Bandwidth Monitor (nlbwmon) is a lightweight, efficient traffic accounting program keeping track of bandwidth usage per host and protocol."))
14
15 nw.init(luci.model.uci.cursor_state())
16
17 s = m:section(TypedSection, "nlbwmon")
18 s.anonymous = true
19 s.addremove = false
20 s:tab("general", translate("General Settings"))
21 s:tab("advanced", translate("Advanced Settings"))
22 s:tab("protocol", translate("Protocol Mapping"),
23         translate("Protocol mappings to distinguish traffic types per host, one mapping per line. The first value specifies the IP protocol, the second value the port number and the third column is the name of the mapped protocol."))
24
25 period = s:taboption("general", ListValue, "_period", translate("Accounting period"),
26         translate("Choose \"Day of month\" to restart the accounting period monthly on a specific date, e.g. every 3rd. Choose \"Fixed interval\" to restart the accounting period exactly every N days, beginning at a given date."))
27
28 period:value("relative", translate("Day of month"))
29 period:value("absolute", translate("Fixed interval"))
30
31 period.write = function(self, cfg, val)
32         if period:formvalue(cfg) == "relative" then
33                 m:set(cfg, "database_interval", interval:formvalue(cfg))
34         else
35                 m:set(cfg, "database_interval", "%s/%s" %{
36                         date:formvalue(cfg),
37                         days:formvalue(cfg)
38                 })
39         end
40 end
41
42 period.cfgvalue = function(self, cfg)
43         local val = m:get(cfg, "database_interval") or ""
44         if val:match("^%d%d%d%d%-%d%d%-%d%d/%d+$") then
45                 return "absolute"
46         end
47         return "relative"
48 end
49
50
51 warning = s:taboption("general", DummyValue, "_warning", translate("Warning"))
52 warning.default = translatef("Changing the accounting interval type will invalidate existing databases!<br /><strong><a href=\"%s\">Download backup</a></strong>.", luci.dispatcher.build_url("admin/nlbw/backup"))
53 warning.rawhtml = true
54
55 if (m.uci:get_first("nlbwmon", "nlbwmon", "database_interval") or ""):match("^%d%d%d%d-%d%d-%d%d/%d+$") then
56         warning:depends("_period", "relative")
57 else
58         warning:depends("_period", "absolute")
59 end
60
61
62 interval = s:taboption("general", Value, "_interval", translate("Due date"),
63         translate("Day of month to restart the accounting period. Use negative values to count towards the end of month, e.g. \"-5\" to specify the 27th of July or the 24th of Februrary."))
64
65 interval.datatype = "or(range(1,31),range(-31,-1))"
66 interval.placeholder = "1"
67 interval:value("1", translate("1 - Restart every 1st of month"))
68 interval:value("-1", translate("-1 - Restart every last day of month"))
69 interval:value("-7", translate("-7 - Restart a week before end of month"))
70 interval.rmempty = false
71 interval:depends("_period", "relative")
72 interval.write = period.write
73
74 interval.cfgvalue = function(self, cfg)
75         local val = m:get(cfg, "database_interval")
76         return val and tonumber(val)
77 end
78
79
80 date = s:taboption("general", Value, "_date", translate("Start date"),
81         translate("Start date of the first accounting period, e.g. begin of ISP contract."))
82
83 date.datatype = "dateyyyymmdd"
84 date.placeholder = "2016-03-15"
85 date.rmempty = false
86 date:depends("_period", "absolute")
87 date.write = period.write
88
89 date.cfgvalue = function(self, cfg)
90         local val = m:get(cfg, "database_interval") or ""
91         return (val:match("^(%d%d%d%d%-%d%d%-%d%d)/%d+$"))
92 end
93
94
95 days = s:taboption("general", Value, "_days", translate("Interval"),
96         translate("Length of accounting interval in days."))
97
98 days.datatype = "min(1)"
99 days.placeholder = "30"
100 days.rmempty = false
101 days:depends("_period", "absolute")
102 days.write = period.write
103
104 days.cfgvalue = function(self, cfg)
105         local val = m:get(cfg, "database_interval") or ""
106         return (val:match("^%d%d%d%d%-%d%d%-%d%d/(%d+)$"))
107 end
108
109
110 ifaces = s:taboption("general", Value, "_ifaces", translate("Local interfaces"),
111         translate("Only conntrack streams from or to any of these networks are counted."))
112
113 ifaces.template = "cbi/network_netlist"
114 ifaces.widget = "checkbox"
115 ifaces.nocreate = true
116
117 ifaces.cfgvalue = function(self, cfg)
118         return m:get(cfg, "local_network")
119 end
120
121 ifaces.write = function(self, cfg)
122         local item
123         local items = {}
124         for item in utl.imatch(subnets:formvalue(cfg)) do
125                 items[#items+1] = item
126         end
127         for item in utl.imatch(ifaces:formvalue(cfg)) do
128                 items[#items+1] = item
129         end
130         m:set(cfg, "local_network", items)
131 end
132
133
134 subnets = s:taboption("general", DynamicList, "_subnets", translate("Local subnets"),
135         translate("Only conntrack streams from or to any of these subnets are counted."))
136
137 subnets.datatype = "ipaddr"
138
139 subnets.cfgvalue = function(self, cfg)
140         local subnet
141         local subnets = {}
142         for subnet in utl.imatch(m:get(cfg, "local_network")) do
143                 subnet = ip.new(subnet)
144                 subnets[#subnets+1] = subnet and subnet:string()
145         end
146         return subnets
147 end
148
149 subnets.write = ifaces.write
150
151
152 limit = s:taboption("advanced", Value, "database_limit", translate("Maximum entries"),
153         translate("The maximum amount of entries that should be put into the database, setting the limit to 0 will allow databases to grow indefinitely."))
154
155 limit.datatype = "uinteger"
156 limit.placeholder = "10000"
157
158 prealloc = s:taboption("advanced", Flag, "database_prealloc", translate("Preallocate database"),
159         translate("Whether to preallocate the maximum possible database size in memory. This is mainly useful for memory constrained systems which might not be able to satisfy memory allocation after longer uptime periods."))
160
161 prealloc:depends({["database_limit"] = "0", ["!reverse"] = true })
162
163
164 compress = s:taboption("advanced", Flag, "database_compress", translate("Compress database"),
165         translate("Whether to gzip compress archive databases. Compressing the database files makes accessing old data slightly slower but helps to reduce storage requirements."))
166
167 compress.default = compress.enabled
168
169
170 generations = s:taboption("advanced", Value, "database_generations", translate("Stored periods"),
171         translate("Maximum number of accounting periods to keep, use zero to keep databases forever."))
172
173 generations.datatype = "uinteger"
174 generations.placeholder = "10"
175
176
177 commit = s:taboption("advanced", Value, "commit_interval", translate("Commit interval"),
178         translate("Interval at which the temporary in-memory database is committed to the persistent database directory."))
179
180 commit.placeholder = "24h"
181 commit:value("24h", translate("24h - least flash wear at the expense of data loss risk"))
182 commit:value("12h", translate("12h - compromise between risk of data loss and flash wear"))
183 commit:value("10m", translate("10m - frequent commits at the expense of flash wear"))
184 commit:value("60s", translate("60s - commit minutely, useful for non-flash storage"))
185
186
187 refresh = s:taboption("advanced", Value, "refresh_interval", translate("Refresh interval"),
188         translate("Interval at which traffic counters of still established connections are refreshed from netlink information."))
189
190 refresh.placeholder = "30s"
191 refresh:value("30s", translate("30s - refresh twice per minute for reasonably current stats"))
192 refresh:value("5m", translate("5m - rarely refresh to avoid frequently clearing conntrack counters"))
193
194
195 directory = s:taboption("advanced", Value, "database_directory", translate("Database directory"),
196         translate("Database storage directory. One file per accounting period will be placed into this directory."))
197
198 directory.placeholder = "/var/lib/nlbwmon"
199
200
201 protocols = s:taboption("protocol", TextValue, "_protocols")
202 protocols.rows = 50
203
204 protocols.cfgvalue = function(self, cfg)
205         return fs.readfile("/usr/share/nlbwmon/protocols")
206 end
207
208 protocols.write = function(self, cfg, value)
209         fs.writefile("/usr/share/nlbwmon/protocols", (value or ""):gsub("\r\n", "\n"))
210 end
211
212 protocols.remove = protocols.write
213
214
215 return m