From 4b82433c8a6149f14e24bdca209bfcf54cedbaa3 Mon Sep 17 00:00:00 2001 From: Ted Trask Date: Tue, 13 May 2008 20:02:56 +0000 Subject: Rewrote syslog to use components and remove view-specific code from controller. Also made sure not to write to conf file unless all variables pass validation. git-svn-id: svn://svn.alpinelinux.org/acf/alpine-baselayout/trunk@1116 ab2d0c66-481e-0410-8bed-d214d4d58bed --- alpine-baselayout.roles | 4 +- syslog-basicstatus-html.lsp | 13 +++ syslog-config-html.lsp | 132 +++++----------------- syslog-controller.lua | 197 ++++++--------------------------- syslog-expert-html.lsp | 109 ++++-------------- syslog-model.lua | 262 +++++++++++++++++++------------------------- syslog-startstop-html.lsp | 26 +++++ syslog-status-html.lsp | 43 ++------ 8 files changed, 251 insertions(+), 535 deletions(-) create mode 100644 syslog-basicstatus-html.lsp create mode 100644 syslog-startstop-html.lsp diff --git a/alpine-baselayout.roles b/alpine-baselayout.roles index 6d460bd..7c1ab0d 100644 --- a/alpine-baselayout.roles +++ b/alpine-baselayout.roles @@ -1,5 +1,5 @@ CREATE=interfaces:create -READ=health:storage,health:proc,health:network,health:modules,interfaces:read,logfiles:status,logfiles:view,logfiles:download,syslog:status -UPDATE=interfaces:update,skins:update,skins:read,syslog:config,syslog:expert,interfaces:config +READ=health:storage,health:proc,health:network,health:modules,interfaces:read,logfiles:status,logfiles:view,logfiles:download,syslog:status,syslog:basicstatus +UPDATE=interfaces:update,skins:update,skins:read,syslog:startstop,syslog:config,syslog:expert,interfaces:config DELETE=interfaces:delete,logfiles:delete ALL=health:system diff --git a/syslog-basicstatus-html.lsp b/syslog-basicstatus-html.lsp new file mode 100644 index 0000000..cf1e789 --- /dev/null +++ b/syslog-basicstatus-html.lsp @@ -0,0 +1,13 @@ + + + + +

SYSTEM INFO

+
+ +
diff --git a/syslog-config-html.lsp b/syslog-config-html.lsp index ff068e1..ac5b77e 100644 --- a/syslog-config-html.lsp +++ b/syslog-config-html.lsp @@ -1,4 +1,5 @@ - + + DEBUGGING

DEBUG INFO: CFE

") @@ -7,119 +8,49 @@ io.write("
") --]] ?> -") - for k,v in pairs(tags) do - if (myform[v]) then - local val = myform[v] - io.write("\t" .. val.label .. "\n") - - io.write("\t\t
" .. val.value .. "\n") - if (val.descr) and (#val.descr > 0) then io.write("\t\t

" .. string.gsub(val.descr, "\n", "
") .. "

\n") end - if (val.errtxt) then io.write("\t\t

" .. string.gsub(val.errtxt, "\n", "
") .. "

\n") end - io.write("\t\t
\n") - end - end - io.write("") -end -?> -") - for k,v in pairs(tags) do - if (myform[v]) then - local val = myform[v] - io.write("\t" .. val.label .. "\n") - - io.write("\t\t
" .. html.form[val.type](val) .. "\n") - if (val.descr) and (#val.descr > 0) then io.write("\t\t

" .. string.gsub(val.descr, "\n", "
") .. "

\n") end - if (val.errtxt) then io.write("\t\t

" .. string.gsub(val.errtxt, "\n", "
") .. "

\n") end - io.write("\t\t
\n") - end - end - io.write("") -end -?> - -

SYSTEM INFO

- - -

CONFIGURATION

- -
" method="POST"> - - -

GUIDED CONFIGURATION

-

REMOTE LOGGING

- + + - +

CONFIGURATION

+

") ?>

+

") ?>

+

ADVANCED CONFIGURATION

GENERAL

+
- +

LOGROTATE

- + - +

REMOTE LOGGING

+
- - +

SAVE AND APPLY ABOVE SETTINGS

- +
Save/Apply above settings
- + -
-

MANAGEMENT

-
-
-
- - - - - -
- - 0) then ?> -
Previous action result
-
- -
-
- - + ") --]] ?> - - - diff --git a/syslog-controller.lua b/syslog-controller.lua index b592672..5c47415 100644 --- a/syslog-controller.lua +++ b/syslog-controller.lua @@ -2,186 +2,57 @@ module(..., package.seeall) default_action = "status" -local function getstatus(self) - local status = self.model.getstatus() - if (#status.status.value > 0) then - status.status.value = "Enabled" - else - status.status.value = "Disabled" - end - return status -end - -local function displaycmdsave(self) - -- Add a cmd button to the view - local cmdsave = cfe({ name="cmdsave", - label="Save/Apply above settings", - value="Save", - type="submit", - }) - return cmdsave -end - -local function displaycmdmanagement(disablestart,disablestop,disablerestart) - -- Add a management buttons - local management = {} - management.start = cfe({ name="cmdmanagement", - label="Program control-panel", - value="Start", - type="submit", - }) - management.stop = cfe({ name="cmdmanagement", - label="Program control-panel", - value="Stop", - type="submit", - }) - management.restart = cfe({ name="cmdmanagement", - label="Program control-panel", - value="Restart", - type="submit", - }) - - -- Disable management buttons based on if the process is running or not - if (disablestart) then management.start.disabled = "yes" end - if (disablestop) then management.stop.disabled = "yes" end - if (disablerestart) then management.restart.disabled = "yes" end - - return management -end - function status(self) - return { status=getstatus(self) } + return self.model.getlogging() end function config(self) - local cmdmanagement, cmdmanagementresult - local cmdsavereply = {} - local cmdsaveresult = {} - if ( self.clientdata.cmdmanagement) then - cmdmanagement = cfe({ - name="cmdmanagement", - value=string.lower(self.clientdata.cmdmanagement), - }) - cmdmanagementresult, cmdmanagement = self.model:startstop_service( cmdmanagement ) - end - if ( self.clientdata.cmdsave) then - local variables="logfile loglevel smallerlogs maxsize numrotate localandnetworklog remotelogging" -- Advanced-config options --- local variables="remotelogging" -- Guided-config options - for var in string.gmatch(variables, "%S+") do - -- Send nil instead of "" causes the parameter to be removed/deleted/empty/unset the variable in the config-file - if (self.clientdata[var] == "") then self.clientdata[var] = nil end - cmdsaveresult[var], cmdsavereply[var] = self.model:setconfigs( var,self.clientdata[var] ) - end - end - - local status = getstatus(self) - local config = self.model.getconfig() - - -- Write out erros from previous cmdsave actions - for k,v in pairs(cmdsaveresult) do - if not (v) then - config[k]["errtxt"] = tostring(cmdsavereply[k]["errtxt"]) - end - end - - -- Display save button - config.cmdsave = displaycmdsave() - if (self.clientdata.cmdsave) then - config.cmdsave.descr="* Changes has been saved!" - end - - -- Management buttons - local disablestart,disablestop,disablerestart - -- Disable management buttons based on if the process is running or not - if (string.lower(status.status.value) == "enabled" ) then - disablestart = "yes" + local config + if self.clientdata.save then + config = self.model.updateconfig(self.clientdata) else - disablestop = "yes" - end - -- Disable management buttons if there exist errors in the config - for k,v in pairs(config) do - if (config[k]["errtxt"]) then - disablestart = "yes" - disablestop = "yes" - disablerestart = "yes" - break - end + config = self.model.getconfig() end - -- Display management buttons - local management = displaycmdmanagement(disablestart,disablestop,disablerestart) - - return { - option={ script=ENV["SCRIPT_NAME"], - prefix=self.conf.prefix, - controller = self.conf.controller, - action = "config", }, - status = status, - cmdmanagement = cmdmanagement, - management = management, - config = config, - debugclientdata = self.clientdata, - } + config.type = "form" + + return config end function expert(self) - local cmdmanagement, cmdmanagementresult - if ( self.clientdata.cmdmanagement) then - cmdmanagement = cfe({ - name="cmdmanagement", - value=string.lower(self.clientdata.cmdmanagement), - }) - cmdmanagementresult, cmdmanagement = self.model:startstop_service( cmdmanagement ) - end - -- Save changes local modifications = self.clientdata.filecontent or "" - if ( self.clientdata.cmdsave) then - modifications = self.model:update_filecontent(modifications) + if self.clientdata.save then + self.model:update_filecontent(modifications) end - local status = getstatus(self) local config = self.model:get_filedetails() + config.type = "form" + if self.clientdata.save then + config.descr = "Saved File" + end + return config +end - -- Display save button - config.cmdsave = displaycmdsave() - if (self.clientdata.cmdsave) then - config.cmdsave.descr="* Changes has been saved!" - end - - - -- Management buttons - local disablestart,disablestop,disablerestart - -- Disable management buttons based on if the process is running or not - if (string.lower(status.status.value) == "enabled" ) then - disablestart = "yes" - else - disablestop = "yes" +function startstop(self) + local result + if self.clientdata.action then + result = self.model:startstop_service(self.clientdata.action) + self.sessiondata.syslogstartstopresult = result + self.redirect_to_referrer(self) end - -- Disable management buttons if there exist errors in the config - for k,v in pairs(config) do - if (config[k]["errtxt"]) then - disablestart = "yes" - disablestop = "yes" - disablerestart = "yes" - break - end - end - -- Display management buttons - local management = displaycmdmanagement(disablestart,disablestop,disablerestart) - - return { - option={ script=ENV["SCRIPT_NAME"], - prefix=self.conf.prefix, - controller = self.conf.controller, - action = "expert", }, - cmdmanagement = cmdmanagement, - management = management, - config = config, - status = status, - startstop = startstop, - debugclientdata = self.clientdata, - } + local status = self.model.getstatus() + if self.sessiondata.syslogstartstopresult then + result = self.sessiondata.syslogstartstopresult + self.sessiondata.syslogstartstopresult = nil + end + + return cfe({ type="group", value={status=status, result=result} }) end +function basicstatus(self) + status = self.model.getstatus() + version = self.model.getversion() + return cfe({ type="group", value={status=status, version=version} }) +end diff --git a/syslog-expert-html.lsp b/syslog-expert-html.lsp index 2b1f238..37e1a4f 100644 --- a/syslog-expert-html.lsp +++ b/syslog-expert-html.lsp @@ -1,4 +1,5 @@ - + + DEBUGGING

DEBUG INFO: CFE

") @@ -6,103 +7,41 @@ io.write(html.cfe_unpack(form)) io.write("
") --]] ?> -") - for k,v in pairs(tags) do - if (myform[v]) then - local val = myform[v] - io.write("\t" .. val.label .. "\n") - - io.write("\t\t
" .. val.value .. "\n") - if (val.descr) and (#val.descr > 0) then io.write("\t\t

" .. string.gsub(val.descr, "\n", "
") .. "

\n") end - if (val.errtxt) then io.write("\t\t

" .. string.gsub(val.errtxt, "\n", "
") .. "

\n") end - io.write("\t\t
\n") - end - end - io.write("") -end -?> -") - for k,v in pairs(tags) do - if (myform[v]) then - local val = myform[v] - io.write("\t" .. val.label .. "\n") - - io.write("\t\t
" .. html.form[val.type](val) .. "\n") - if (val.descr) and (#val.descr > 0) then io.write("\t\t

" .. string.gsub(val.descr, "\n", "
") .. "

\n") end - if (val.errtxt) then io.write("\t\t

" .. string.gsub(val.errtxt, "\n", "
") .. "

\n") end - io.write("\t\t
\n") - end - end - io.write("") -end -?> - -

SYSTEM INFO

- + + +

CONFIGURATION

- -
" method="POST"> -

EXPERT CONFIGURATION

FILE DETAILS

+
+

FILE CONTENT

- +

") ?>

+

") ?>

+ +

SAVE AND APPLY ABOVE SETTINGS

- +
Save/Apply above settings
- - -
-

MANAGEMENT

-
-
-
- - - - - -
- - 0) then ?> -
Previous action result
-
- -
-
- - + + + 0 then + configdata[entry] = config.value[name].value + else + configdata[entry] = nil + end + end + + local cmdresult, cmdmessage, cmderror = getopts.setoptsinfile(configfile,"",variable,'"' .. getopts.table_to_opts(configdata) .. '"') + return cmdmessage, cmderror +end + -- ################################################################################ -- PUBLIC FUNCTIONS --- action should be a CFE function startstop_service ( self, action ) - local cmd = action.value - local cmdresult,cmdmessage,cmderror,cmdaction = daemoncontrol.daemoncontrol(processname, cmd) - action.descr=cmdmessage - action.errtxt=cmderror - -- Reporting back (true|false, the original acition) - return cmdresult,action - + local cmdresult,cmdmessage,cmderror,cmdaction = daemoncontrol.daemoncontrol(processname, action) + return cfe({ type="boolean", value=cmdresult, descr=cmdmessage, errtxt=cmderror, label=action.." result" }) end -function getstatus() - local opts = getconfig() - local status = {} - status.version = cfe({ name = "version", +function getversion() + return cfe({ label="Program version", value=get_version(), }) - status.status = cfe({ name="status", +end + +function getstatus() + local status = cfe({ label="Program status", value=procps.pidof("syslogd"), }) - if (opts["remotelogging"]) and not ((opts["remotelogging"]["value"] ~= "") and not (opts["localandnetworklog"]["value"])) then - status.logfile = cfe({ name="logfile", + if (#status.value > 0) then + status.value = "Enabled" + else + status.value = "Disabled" + end + return status +end + +function getlogging() + local status = {} + local opts = getconfig() + if (opts.value.remotelogging.value == "") or (opts.value.localandnetworklog.value) then + status.logfile = cfe({ label="Locally logging to", - value=opts["logfile"]["value"], + value=opts.value.logfile.value, }) end - if (opts["SYSLOGD_OPTS"]) and (opts["SYSLOGD_OPTS"]["-R"]) and (opts["SYSLOGD_OPTS"]["-R"] ~= "") then - status.remote = cfe({ name="remotelogging", + if (opts.value.remotelogging.value ~= "") then + status.remote = cfe({ label="Remote logging to", - value=opts["SYSLOGD_OPTS"]["-R"], + value=opts.value.remotelogging.value, }) end - return status + return cfe({ type="group", value=status }) end function get_filedetails() @@ -73,200 +108,125 @@ function get_filedetails() local config = getconfig(path) local file = {} file["filename"] = cfe({ - name="filename", label="File name", value=path, }) file["filesize"] = cfe({ - name="filesize", label="File size", - value=filedetails.size or 0, + value=filedetails.size or "0", }) file["mtime"] = cfe({ - name="mtime", label="File date", value=filedetails.mtime or "---", }) file["filecontent"] = cfe({ type="longtext", - name="filecontent", label="File content", value=fs.read_file(path), }) - file["sumerrors"] = config.sumerrors - - return file + return cfe({ type="group", value=file, label="Config file details" }) end + function getconfig() local config = {} if (fs.is_file(configfile)) then configcontent = getopts.getoptsfromfile(configfile, "", "SYSLOGD_OPTS", true) or {} else - config["configfile"] = "Config file '".. configfile .. "' is missing!" + config["errtxt"] = "Config file '".. configfile .. "' is missing!" end -- Next section selects which configurations we should show to the user config["logfile"] = cfe({ - name="logfile", label = "Log to given file", + descr = "File must be in /var/log directory", value = configcontent["-O"] or "/var/log/messages", }) config["loglevel"] = cfe({ - name="loglevel", label = "Set local log level", - value = tonumber(configcontent["-l"]) or 8, + value = configcontent["-l"] or "8", type = "select", option = getloglevels(), descr = "1=Quiet, ... , " .. table.maxn(getloglevels()) .. "=Debug", }) config["smallerlogs"] = cfe({ - name="smallerlogs", label = "Smaller logging output", - checked = configcontent["-S"], - value = "smallerlogs", - type = "checkbox", + value = (configcontent["-S"] == ""), + type = "boolean", }) config["maxsize"] = cfe ({ - name="maxsize", label = "Max size (KB) before rotate", descr = "Default=200KB, 0=off", - value = configcontent["-s"], + value = configcontent["-s"] or "", }) - config["numrotate"] = cfe ({ name="numrotate", + config["numrotate"] = cfe ({ label = "Number of rotated logs to keep", descr = "Default=1, max=99, 0=purge", - value = configcontent["-b"], + value = configcontent["-b"] or "", }) config["localandnetworklog"] = cfe ({ - name="localandnetworklog", label = "Log locally and via network", - checked = configcontent["-L"], - value = "localandnetworklog", - type = "checkbox", - descr = "Default is network only if -R", + value = (configcontent["-L"] == ""), + type = "boolean", + descr = "Default is network only if host[:PORT] is defined", }) config["remotelogging"] = cfe ({ - name="remotelogging", label = "Log to IP or hostname on PORT", descr = "host[:PORT] - Default PORT=514/UDP", - value = configcontent["-R"], + value = configcontent["-R"] or "", }) - -- Next section is to print errormessages when configs are wrong - if (configcontent["-l"]) and - ((tonumber(configcontent["-l"]) == nil) or (tonumber(configcontent["-l"]) > 8)) then - config["loglevel"]["errtxt"] = "Log value is out of range!\nCurrent value in config is '" .. - configcontent["-l"] .. - "' - This is invalid!\nPlease select one of the above and save your changes." - table.insert(config["loglevel"]["option"], tonumber(configcontent["-l"])) - end + return cfe({ type="group", value=config, label="Configuration" }) +end - if (configcontent["-L"] ~= nil) and ((configcontent["-R"] == nil) or (configcontent["-R"] == "")) then - config["localandnetworklog"]["errtxt"] = "Logging to local and network (-L) is not possible unless you define a host (-R) for remote logging or remove this option." +function updateconfig (clientdata) + local config = getconfig() + local success = true + for name in pairs(config.value) do + if config.value[name].type == "boolean" then + config.value[name].value = (clientdata[name] == "true") + elseif clientdata[name] then + config.value[name].value = clientdata[name] + end end - -- Sum all errors into one cfe - local sumerrors = "" - for k,v in pairs(config) do - if (config[k]["errtxt"]) then - sumerrors = sumerrors .. config[k]["errtxt"] .. "\n" - end + -- Validate entries and create error strings + if not validator.is_valid_filename(config.value.logfile.value, "/var/log") then + config.value.logfile.errtxt = "Not a valid file name in /var/log" + success = false end - if (sumerrors ~= "") then - config["sumerrors"] = cfe ({ - name="sumerrors", - label = "Configuration errors", - errtxt = sumerrors, - }) + if not validator.is_integer_in_range(config.value.loglevel.value, 1, 8) then + config.value.loglevel.errtxt = "Out of range!" + success = false end - - return config -end - --- IMPORTANT! This function is a exception! It's not fed with CFE's --- Parameter should be one of the ones defined in the variable 'variabletranslator'. --- value should be whatever the new value should be. -function setconfigs(self,parameter,value) - -- Set variables - local variable = "SYSLOGD_OPTS" - local variabletranslator = ({ - logfile = "-O", - loglevel = "-l", - smallerlogs = "-S", - maxsize = "-s", - numrotate = "-b", - localandnetworklog = "-L", - remotelogging = "-R", - }) - cmdparameter = variabletranslator[parameter] - - -- Report a error if someone tryes to use a invalid parameter - if not (cmdparameter) then - local availablevariables = "" - for k,v in pairs(variabletranslator) do - availablevariables = k .. ", " .. availablevariables - end - parameter = parameter or "" - return false, cfe({ - name="syslog.model.setconfigs()", - errtxt="'" .. parameter .. "' is not a valid parameter!\nValid options are: " .. availablevariables, - }) + if config.value.maxsize.value ~= "" and not validator.is_integer(config.value.maxsize.value) then + config.value.maxsize.errtxt = "Must be an integer" + success = false end - - --TODO: Validate so that user cant add values with '-' (could cause major breakage next time you do getopts) - - -- This config-file only accepts one type of parameters (report error if someone uses wrong parameter) - if not (string.find(cmdparameter, "-%a$")) then - return false, cfe({ - name="syslog.model.setconfigs()", - errtxt="Parameter must be formated '-a' (where a is one upper/lowercase letter [a-z])", - }) + if config.value.numrotate.value ~= "" and not validator.is_integer_in_range(config.value.numrotate.value, 0, 99) then + config.value.numrotate.errtxt = "Out of range!" + success = false end - - -- Validate userinput (if valid path/filename) - if (value) and (cmdparameter == "-O") then - local cmdresult, cmdmessage = validator.is_valid_filename(value, "/var/log" ) - if not (cmdresult) then - return false, cfe({ - name="syslog.model.setconfigs()", - errtxt=cmdmessage, - }) - end + if config.value.localandnetworklog.value == true and config.value.remotelogging.value == "" then + config.value.localandnetworklog.errtxt = "Logging to local and network is not possible unless you define a host for remote logging" + success = false end - - -- Validate userinput (Has the user entered a valid hostname and/or port) - if (value) and (cmdparameter == "-R") then - local hostport = format.string_to_table(value, ":") - local host = hostport[1] - local port = hostport[2] - if (port) and not (validator.is_port(port)) then - return false, cfe({ - name="syslog.model.setconfigs.getopts.setoptsinfile()", - errtxt="You entered '" .. tostring(port) .. "' as port - This is not valid!", - }) - end + local hostport = format.string_to_table(config.value.remotelogging.value, ":") + if hostport[2] and not (validator.is_port(hostport[2])) then + config.value.remotelogging.errtxt = "Not a valid port" + success = false end - -- Set/Unset checkbox variables - if (value) and ((cmdparameter == "-S") or (cmdparameter == "-L")) then value = "" end - - local cmdresult, cmdmessage, cmderror = getopts.setoptsinfile(configfile,"",variable,cmdparameter,true,value) - if (cmderror) then - return false, cfe({ - name="syslog.model.setconfigs.getopts.setoptsinfile()", - errtxt=cmderror, - }) + if success == true then + config.descr, config.errtxt = writeconfig(config) + else + config.errtxt = "Failed to save config!" end - return true, cfe({ - name="syslog.model.setconfigs()", - value=cmdmessage, - }) + + return config end --- modifications should be a CFE function update_filecontent (self, modifications) local path = configfile - local file_result,err = fs.write_file(path, format.dostounix(modifications)) - return file_result, err + fs.write_file(path, format.dostounix(modifications)) end diff --git a/syslog-startstop-html.lsp b/syslog-startstop-html.lsp new file mode 100644 index 0000000..f3f7013 --- /dev/null +++ b/syslog-startstop-html.lsp @@ -0,0 +1,26 @@ + + + +

MANAGEMENT

+
+
+
Program control-panel
+
+> +> +> +
+
+ + +
Previous action result
+
+ +

") ?>

+ +

") ?>

+ +
+
diff --git a/syslog-status-html.lsp b/syslog-status-html.lsp index 5b5a8f7..f68147d 100644 --- a/syslog-status-html.lsp +++ b/syslog-status-html.lsp @@ -1,4 +1,5 @@ - + + DEBUGGING

DEBUG INFO: CFE

") @@ -6,39 +7,17 @@ io.write(html.cfe_unpack(form)) io.write("
") --]] ?> -") - for k,v in pairs(tags) do - if (myform[v]) then - local val = myform[v] - io.write("\t" .. val.label .. "\n") - - io.write("\t\t
" .. val.value .. "\n") - if (val.descr) and (#val.descr > 0) then io.write("\t\t

" .. string.gsub(val.descr, "\n", "
") .. "

\n") end - if (val.errtxt) then io.write("\t\t

" .. string.gsub(val.errtxt, "\n", "
") .. "

\n") end - io.write("\t\t
\n") - end - end - io.write("") -end -?> -

SYSTEM INFO

- + + +

PROGRAM SPECIFIC OPTIONS/INFORMATION

+
- - - +
-- cgit v1.2.3