-
Notifications
You must be signed in to change notification settings - Fork 96
/
config.lua
234 lines (194 loc) · 7.31 KB
/
config.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/usr/bin/lua
--! LibreMesh is modular but this doesn't mean parallel, modules are executed
--! sequencially, so we don't need to worry about transactionality and all other
--! stuff that affects parrallels database, at moment we don't need parallelism
--! as this is just some configuration stuff and is not performance critical.
local fs = require("nixio.fs")
local libuci = require("uci")
local nixio = require "nixio"
config = {}
function config.log(text)
nixio.syslog('info', '[config] ' .. text)
end
config.uci = nil
config.hooksDir = "/etc/hotplug.d/lime-config"
function config.get_uci_cursor()
if config.uci == nil then
config.uci = libuci:cursor()
end
return config.uci
end
function config.set_uci_cursor(cursor)
config.uci = cursor
end
config.uci = config.get_uci_cursor()
config.UCI_AUTOGEN_NAME = 'lime-autogen'
config.UCI_NODE_NAME = 'lime-node'
config.UCI_MAC_NAME = 'lime-000000000000'
config.UCI_COMMUNITY_NAME = 'lime-community'
config.UCI_DEFAULTS_NAME = 'lime-defaults'
config.UCI_CONFIG_NAME = config.UCI_AUTOGEN_NAME
function config.get_config_path()
return config.uci:get_confdir() .. '/' .. config.UCI_CONFIG_NAME
end
function config.reset_node_config()
config.initialize_config_file(config.UCI_NODE_NAME)
end
function config.initialize_config_file(config_name)
local lime_path = config.uci:get_confdir() .. "/" .. config_name
os.execute(string.format('cp /usr/share/lime/configs/%s %s', config_name, lime_path))
end
function config.get(sectionname, option, fallback)
local limeconf = config.uci:get(config.UCI_CONFIG_NAME, sectionname, option)
if limeconf then return limeconf end
if ( fallback ~= nil ) then
config.log("Use fallback value for "..sectionname.."."..option..": "..tostring(fallback))
return fallback
else
config.log("WARNING: Attempt to access undeclared default for: "..sectionname.."."..option)
config.log(debug.traceback())
return nil
end
end
--! Execute +callback+ for each config of type +configtype+ found in
--! +/etc/config/lime-autogen+.
function config.foreach(configtype, callback)
return config.uci:foreach(config.UCI_CONFIG_NAME, configtype, callback)
end
function config.get_all(sectionname)
return config.uci:get_all(config.UCI_CONFIG_NAME, sectionname)
end
function config.get_bool(sectionname, option, default)
local val = config.get(sectionname, option, default)
return (val and ((val == '1') or (val == 'on') or (val == 'true') or (val == 'enabled') or (val == 1) or (val == true)))
end
config.batched = false
function config.init_batch()
config.batched = true
end
function config.set(...)
local aty = type(arg[3])
if (aty ~= "nil" and aty ~= "string" and aty ~= "table") then
arg[3] = tostring(arg[3])
end
config.uci:set(config.UCI_CONFIG_NAME, unpack(arg))
if(not config.batched) then config.uci:save(config.UCI_CONFIG_NAME) end
end
function config.delete(...)
config.uci:delete(config.UCI_CONFIG_NAME, unpack(arg))
if(not config.batched) then config.uci:save(config.UCI_CONFIG_NAME) end
end
function config.end_batch()
if(config.batched) then
config.uci:save(config.UCI_CONFIG_NAME)
config.batched = false
end
end
function config.autogenerable(section_name)
return ( (not config.get_all(section_name)) or config.get_bool(section_name, "autogenerated") )
end
--! Merge two uci files. If an option exists in both files the value of high_prio is selected
function config.uci_merge_files(high_prio, low_prio, output)
local uci = config.get_uci_cursor()
local high_pt = uci:get_all(high_prio)
local low_pt = uci:get_all(low_prio)
--! populate high_prio with low_prio values that are not in high_prio
for section_name, section in pairs(low_pt) do
local high_section = high_pt[section_name]
if high_section ~= nil then
--! copy only some attributes
for option_name, option in pairs(section) do
--! if the options starts with a dot it is not a real options it is an attribute
--! like .name, .type, .anonymous and .index
if option_name[1] ~= '.' and high_section[option_name] == nil then
high_section[option_name] = option
end
end
else
high_pt[section_name] = section
end
end
--! populate output from high_prio using uci
for section_name, section in pairs(high_pt) do
local section_type = section['.type']
uci:set(output, section_name, section_type)
for option_name, option in pairs(section) do
--! if the options starts with a dot it is not a real options it is an attribute
--! like .name, .type, .anonymous and .index
if option_name[1] ~= '.' then
local otype = type(option)
if (otype ~= "nil" and otype ~= "string" and otype ~= "table") then
option = tostring(option)
end
uci:set(output, section_name, option_name, option)
end
end
end
uci:commit(output)
end
function config.uci_autogen()
--! start clearing the config
local f = io.open(config.get_config_path(), "w")
f:write('')
f:close()
--! clean uci cache
local uci = config.get_uci_cursor()
uci:load(config.UCI_AUTOGEN_NAME)
for _, cfg_name in pairs({config.UCI_DEFAULTS_NAME, config.UCI_COMMUNITY_NAME, config.UCI_MAC_NAME, config.UCI_NODE_NAME}) do
local cfg = io.open(config.uci:get_confdir() .. '/' .. cfg_name)
if cfg ~= nil then
config.uci_merge_files(cfg_name, config.UCI_AUTOGEN_NAME, config.UCI_AUTOGEN_NAME)
end
end
uci:load(config.UCI_AUTOGEN_NAME)
end
--! commit all uci changes not yet commited
function config.uci_commit_all()
local uci = config.get_uci_cursor()
for k, _ in pairs(uci:changes()) do
assert(uci:commit(k))
end
end
function config.main()
--! Get mac address and set mac-based configuration file name
local network = require("lime.network")
config.UCI_MAC_NAME = "lime-" .. table.concat(network.primary_mac(),"")
print("Mac-config: " .. config.UCI_MAC_NAME)
--! Populate the default template configs if lime-node and lime-community
--! are not found in /etc/config
for _, cfg_name in pairs({config.UCI_COMMUNITY_NAME, config.UCI_NODE_NAME}) do
local lime_path = config.uci:get_confdir() .. "/" .. cfg_name
local cf = io.open(lime_path)
if not cf then
config.initialize_config_file(cfg_name)
else
cf:close()
end
end
config.uci_autogen()
local modules_name = { "hardware_detection", "wireless", "network", "firewall", "system",
"generic_config" }
local modules = {}
for i, name in pairs(modules_name) do modules[i] = require("lime."..name) end
for _,module in pairs(modules) do
xpcall(module.clean, function(errmsg) print(errmsg) ; print(debug.traceback()) end)
end
for _,module in pairs(modules) do
xpcall(module.configure, function(errmsg) print(errmsg) ; print(debug.traceback()) end)
end
for hook in fs.dir(config.hooksDir) do
local hookCmd = config.hooksDir.."/"..hook.." after"
print("executed hook:", hookCmd, os.execute(hookCmd))
end
local utils = require("lime.utils") -- here to break circular require
local cfgpath = config.get_config_path()
--! flush all config changes
local uci = config.get_uci_cursor()
uci:commit(config.UCI_CONFIG_NAME)
local autogen_content = utils.read_file(cfgpath) or ''
notice_message = ('# DO NOT EDIT THIS FILE!. This is autogenerated by lime-config!\n' ..
'# Instead please edit /etc/config/lime-node and/or /etc/config/lime-community files\n' ..
'# and then regenerate this file executing lime-config\n\n')
utils.write_file(cfgpath, notice_message .. autogen_content)
end
return config