module(..., package.seeall) -- Load libraries require("modelfunctions") require("posix") require("fs") require("format") require("date") require("validator") -- Set variables local configfile = "/etc/rrdtool/acf-rrdtool.conf" local databases = "/etc/rrdtool/databases" local processname = "rrdtool" local packagename = "rrdtool" local header = "rrdtool" local path="PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " -- ################################################################################ -- LOCAL FUNCTIONS -- Function to recursively insert all filenames in a dir into an array local function recursedir(path, filearray) filearray = filearray or {} local k,v for k,v in pairs(posix.dir(path) or {}) do -- Ignore files that begins with a '.' if not string.match(v, "^%.") then local f = path .. "/" .. v -- If subfolder exists, list files in this subfolder if (posix.stat(f).type == "directory") then recursedir(f, filearray) else table.insert(filearray, f) end end end return filearray end local function file_info ( path ) local st = fs.stat(path) local size = st.size or "0" local lastmod = st.mtime or "---" return lastmod,size end local function list_files () local listed_files = {} local open_files = {} local files = {} local k,v -- Generate a single table with all the files for k,v in pairs{databases} do recursedir(v, files) end -- Loop through each file and present its info for k,v in pairs(files) do -- Get info on this specific file and put it in a table local lastmod,size = file_info(v) local filename = cfe({ value=v, label="File name" }) local filesize = cfe({ value=size, label="File size" }) local mtime = cfe({ value=lastmod, label="File date" }) table.insert ( listed_files , cfe({ type="group", value={filename=filename, filesize=filesize, mtime=mtime, label="File details"} }) ) end table.sort(listed_files, function (a,b) return (a.value.filename.value < b.value.filename.value) end ) return cfe({ type="list", value=listed_files, label="Log files" }) end local function validfilename(path) local files = list_files() for k,v in pairs(files.value) do if (v["value"]["filename"]["value"] == path) then return true, tostring(v["value"]["filename"]["value"]) end end return false, "Not a valid filename!" end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) return modelfunctions.startstop_service(processname, action) end function getstatus() return modelfunctions.getstatus(processname, packagename, header .. " status") end function getconfigfile() return modelfunctions.getfiledetails(configfile) end function setconfigfile(filedetails) return modelfunctions.setfiledetails(filedetails, {configfile}) end function getrrdlist() return list_files() end function createnewrrd() local newdb = {} newdb.filename = cfe({label="Name",value="mydb.rrd",descr="The name of the RRD you want to create. RRD files should end with the extension .rrd. However, RRDtool will accept any filename."}) newdb.start = cfe({label="Start",value="",descr="Specifies the time in seconds since 1970-01-01 UTC when the first value should be added to the RRD. RRDtool will not accept any data timed before or at the time specified.\ (Your system saids that your current time is '" .. tostring(os.time(os.date("*t"))) .. "' in the format you should specify above. The startvalue should be smaller than your current time.)\ (Default: now - 10s)"}) newdb.step = cfe({label="Step",value="",descr="Specifies the base interval in seconds with which data will be fed into the RRD.\ (Default: 300)"}) newdb.ds = cfe({label="Data store(s)",value="",descr="DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max \ DS:ds-name:COMPUTE:rpn-expression",type="longtext"}) newdb.rra = cfe({label="Round Robin Archive(s)",value="",descr="RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows",type="longtext"}) return {value=newdb} end function remove_file(self, path, userid) local success = "Failed to delete file" local errtxt if not (fs.is_file(path)) then errtxt = "File doesn't exist!" elseif (validfilename(path)) then os.remove(path) success = "File Deleted" else errtxt = "Not a valid filename!" end return cfe({ value=success, label="Delete config file result", errtxt=errtxt }) end function rrd_info(self, path, userid) local success, errtxt if (validfilename(path)) then local f = io.popen( "/usr/bin/rrdtool info ".. tostring(path) ) success = f:read("*a") or "" f:close() end return cfe({ value=success, label="rrdtool info ".. tostring(path) , errtxt=errtxt }) end function savenewrrd(self, configfile, userid) path=tostring(databases).."/"..configfile.value.filename.value configfile.errtxt = "Failed to create file" local path = configfile.value.filename.value if not string.find(path, "/") then path = databases .. "/" .. path elseif not validator.is_valid_filename(path,databases) then configfile.value.filename.errtxt = "Not a valid path!\ If you specify path, it should be " .. tostring(databases) .."/" return configfile end if (posix.stat(path)) then configfile.value.filename.errtxt = "File already exists" elseif not tonumber(configfile.value.start.value) then configfile.value.start.errtxt = "Only numeric values!" return configfile elseif not tonumber(configfile.value.step.value) then configfile.value.step.errtxt = "Only numeric values!" return configfile else local start,step if (#configfile.value.start.value > 0) then start = "--start " .. tostring(configfile.value.start.value) .. " " else start = "" end if (#configfile.value.step.value > 0) then step = "--step " .. tostring(configfile.value.step.value) .. " " else step = "" end local f = io.popen( "/usr/bin/rrdtool create ".. format.escapespecialcharacters(path) .. " " .. format.escapespecialcharacters(start) .. format.escapespecialcharacters(step) .. tostring(string.gsub(format.dostounix(format.escapespecialcharacters(configfile.value.ds.value)),"\n", " \\\n")) .. " " .. tostring(string.gsub(format.dostounix(format.escapespecialcharacters(configfile.value.rra.value)),"\n", " \\\n")) .. " 2>&1") success = f:read("*a") or "" f:close() configfile.errtxt = tostring(success) end return configfile end