nimd/src/util/config.nim

132 lines
5.3 KiB
Nim

# Copyright 2021 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import tables
import parsecfg
import strutils
import strformat
import logging
import ../core/fs
type
NimDConfig* = ref object
## Configuration object
logLevel*: LogLevel
logFile*: string
workers*: int
directories*: seq[Directory]
symlinks*: seq[Symlink]
filesystems*: seq[Filesystem]
restartDelay*: int
sigtermDelay*: int
autoMount*: bool
autoUnmount*: bool
fstab*: string
sock*: string
onDependencyConflict*: string
setHostname*: bool
const defaultSections* = ["Misc", "Logging", "Filesystem"]
const defaultConfig* = {
"Logging": {
"logFile": "/var/log/nimd",
"level": "info"
}.toTable(),
"Misc": {
"controlSocket": "/var/run/nimd.sock",
"onDependencyConflict": "skip",
"setHostname": "true",
"workers": "1",
"sigtermDelay": "90",
"restartDelay": "30"
}.toTable(),
"Filesystem": {
"autoMount": "true",
"autoUnmount": "true",
"fstabPath": "/etc/fstab",
"createDirs": "",
"createSymlinks": "",
"virtualDisks": ""
}.toTable()
}.toTable()
const levels = {
"trace": Trace,
"debug": Debug,
"info": Info,
"warning": Warning,
"error": Error,
"critical": Critical,
"fatal": Fatal
}.toTable()
proc parseConfig*(logger: Logger, file: string = "/etc/nimd/nimd.conf"): NimDConfig =
## Parses NimD's configuration file
## and returns a configuration object
# Yes this code is far from perfect, but I hate paesing
# config files :(
logger.debug(&"Reading config file at {file}")
let cfgObject = loadConfig(file)
var data = newTable[string, TableRef[string, string]]()
var existingSections: seq[string] = @[]
var directories: seq[Directory] = @[]
var filesystems: seq[Filesystem] = @[]
var symlinks: seq[Symlink] = @[]
var temp: seq[string] = @[]
for section in cfgObject.sections():
existingSections.add(section)
for section in defaultSections:
logger.debug(&"Parsing section '{section}'")
if section notin existingSections:
logger.warning(&"Missing section '{section}' from config file, falling back to defaults")
for (value, key) in defaultConfig[section].pairs():
data[section][value] = key
elif section notin defaultSections:
logger.warning(&"Unknown section '{section}' found in config file, skipping it")
else:
if not data.hasKey(section):
data[section] = newTable[string, string]()
for key in defaultConfig[section].keys():
data[section][key] = cfgObject.getSectionValue(section, key, defaultConfig[section][key])
for dirInfo in data["Filesystem"]["createDirs"].split(","):
temp = dirInfo.split(":")
directories.add(newDirectory(temp[0].strip(), uint64(parseInt(temp[1].strip()))))
for symInfo in data["Filesystem"]["createSymlinks"].split(","):
temp = symInfo.split(":")
symlinks.add(newSymlink(temp[0], temp[1]))
if data["Logging"]["level"] notin levels:
logger.warning(&"""Unknown logging level '{data["Logging"]["level"]}', defaulting to '{defaultConfig["Logging"]["level"]}'""")
data["Logging"]["level"] = defaultConfig["Logging"]["level"]
result = NimDConfig(logLevel: levels[data["Logging"]["level"]],
logFile: data["Logging"]["logFile"],
filesystems: filesystems,
symlinks: symlinks,
directories: directories,
autoMount: parseBool(data["Filesystem"]["autoMount"].toLowerAscii()),
autoUnmount: parseBool(data["Filesystem"]["autoUnmount"].toLowerAscii()),
fstab: data["Filesystem"]["fstabPath"],
sock: data["Misc"]["controlSocket"],
onDependencyConflict: data["Misc"]["onDependencyConflict"].toLowerAscii(),
restartDelay: parseInt(data["Misc"]["restartDelay"]),
sigtermDelay: parseInt(data["Misc"]["sigtermDelay"]),
workers: parseInt(data["Misc"]["workers"]),
setHostname: parseBool(data["Misc"]["setHostname"])
)