require("KLua") require "lfs" require('monitorXml') -- version 1.0 -------------------------------------------------------------------------------------------------- -- Command syntax: c:\lua\5.1\lua.exe "c:\kworking\kmonitorsets\kaseyamonitor.lua" "c:\Kworking" (!!!!! NO TRAILING \) -- First parameter: the lua script -- Second parameter: the agent temp directory, by convention, it always ends with "NO" trailing '\' (don't get smart with me on this) -- *** BOTH parameters are required *** -- For the first release, the kaseyamonitor.lua is always in the directory: [agenttemp]\Kmonitorsets\ for the sake of simplicity of implementation -- (1) ProcessStop.txt -------------------------------------------------------------------------------------------------- -- PROD release: MUST be false for this DEBUG_MODE = true function file_exists(name) local f=io.open(name,"r") if f~=nil then io.close(f) return true else return false end end ---------------------------------------------------------------------------------------------- -- function that process a monitorset clean file -- The clean file contains all known and valid counters according to the KServer, by the end of this process, -- only counters contained in the clean file will be present on the Agent machine ---------------------------------------------------------------------------------------------- function processCleanMonsetFile(cleanFile, allCountersPath) debugInfo("Clean all counters using ".. cleanFile); -- load the xml file local xfile = io.open(cleanFile, "r") if (xfile ~= nil) then -- let's reload all the counters from the txt file local file = io.open(allCountersPath) local content = file.read(file,"*a") io.close(file) local lookFor = "KCTR%$(%w+)%s+Counter%s+(%a+)" xContent = xfile.read(xfile, "*a"); for k, v in string.gmatch(content, lookFor) do -- is the ID we are looking for from the clean file, if it doesn't exist in the clean debugInfo("checking existing agent counterID:", k) local s = string.find(xContent, "") if(s == nil) then debugInfo("remove stale KCTR, ID:", k) logmanRemove(k, nil) end -- and Remember all the counters we know defined and their status end -- Close the xfile io.close(xfile); end end ---------------------------------------------------------------------------------------------- -- function that process a monitorset remove file ---------------------------------------------------------------------------------------------- function processRemoveMonsetFile(removeFile, eventFile) -- load the xml file deployFile = string.format("KMON$%d.xml", string.match(removeFile, "(%d+).")) -- load the XML file on the agent according to the LUA local xfile = nil if file_exists(deployFile) then debugInfo("Remove Monitorset using ".. deployFile); xfile = xml.load(deployFile) if (xfile ~= nil) then counters = xfile:find("Counters") ; if (counters == nil) then os.rename(deployFile, eventFile); else --Now: we need to work with the counters for iIndex = 1, #counters do oneRow = counters[iIndex] local logFile = oneRow.LogFile; local counterID = oneRow.ID; --stop the counter logmanRemove(counterID, logFile); end os.rename(deployFile, eventFile) end os.remove(removeFile) end else if file_exists(removeFile) then debugInfo("Remove Monitorset using ".. removeFile); xfile = xml.load(removeFile) if (xfile ~= nil) then counters = xfile:find("Counters") ; if (counters == nil) then debugInfo("file contains no counters"); os.rename(removeFile, eventFile); else --Now: we need to work with the counters for iIndex = 1, #counters do oneRow = counters[iIndex] local logFile = oneRow.LogFile; local counterID = oneRow.ID; --stop the counter logmanRemove(counterID, logFile); end os.rename(removeFile, eventFile) end else debugInfo("file contains no content, remove only"); os.rename(removeFile, eventFile) end end end end function logmanRemove(counterID, logFile) debugInfo("stop and delete counter, ignore the error if non-existing"); --stop the counter local stopCmd = os.getenv("windir").."\\system32\\".."logman.exe stop ".."KCTR$"..counterID; os.execute (stopCmd) --delete the counter local deleteCmd = os.getenv("windir").."\\system32\\".."logman.exe delete ".."KCTR$"..counterID; os.execute (deleteCmd) --remove the logfile if (logFile ~= nil) then debugInfo("Remove logfile " .. logFile); os.remove(logFile) end end ---------------------------------------------------------------------------------------------- -- function that process a monitorset file ---------------------------------------------------------------------------------------------- function processMonsetFile(name) local priorObject = "" local file = name local fileChanged = false; -- load the xml file local xfile = xml.load(file) if (xfile ~= nil) then local setProp = xfile:find("MonitorSet") local matchCounter = setProp.enableMatch; if (matchCounter == nil) then matchCounter = 0 end debugInfo("Counter matching ... " .. matchCounter); local osType = setProp.osType; debugInfo("osType ... " .. osType); if (osType == nil) then osVersion = "6.0" debugInfo("osType is null and default osVersion is" ..osVersion); else --OS Version: 6.1.7601 Service Pack 1 Build 7601 --Windows 7 6.1 --Windows Server 2008 R2 6.1 --Windows Server 2008 6.0 --Windows Vista 6.0 --Windows Server 2003 R2 5.2 --Windows Server 2003 5.2 --Windows XP 64-Bit Edition 5.2 --Windows XP 5.1 --Windows 2000 5.0 if (osType == "XP" or osType == "2003") then osVersion = "5.0" debugInfo("osType is XP or 2003 and osVersion is: " ..osVersion); else osVersion = "6.0" end end debugInfo("Os Version Info in the set is: " .. osVersion) local counters = xfile:find("Counters") if (counters ~= nil) then -- this way of index to all counters in the defined XML file --for iIndex = 1, (# xfile[1][1]) do for iIndex = 1, #counters do oneRow = counters[iIndex] -- this is ignoring all pre-6.3 files whose CounterObject attr. will be empty or null, ignore all these files if (oneRow.CounterObject ~= nil) then -- depending on existence of instances, construct the string used local lookFor = "" if (oneRow.CounterInstance == nil or oneRow.CounterInstance == "") then lookFor = oneRow.CounterObject.."\\"..oneRow.Counter else lookFor = oneRow.CounterObject.."("..oneRow.CounterInstance..")".."\\"..oneRow.Counter end debugInfo("*** Counter:", lookFor) if (oneRow.CounterInstance == "*ALL") then debugInfo ("Perform miniScan for *ALL ") -- For any counter that contains *ALL as instance, we have to re-do a mini scan, to make sure that any new instances are monitored for this agent pcall(doMiniScan,oneRow.CounterObject,oneRow.Counter, file) else local oldState = oneRow.Active; debugInfo(" counter existing state: ", oldState); --if (oneRow.Active == "1") then debugInfo ("begin checkCounterExistence ") active = checkCounterExistence(oneRow.ID, oneRow.CounterObject, oneRow.Counter, oneRow.CounterInstance, oneRow.Interval, oneRow.LogFile, matchCounter, priorObject) priorObject = oneRow.CounterObject if (active == 1) then debugInfo("This counter is active") oneRow.Active = 1 if (oldState == "0" or oldState == 0 ) then fileChanged = true end else debugInfo("This counter is inactive") oneRow.Active = 0 -- local cstate = {} -- cstate.CounterID = oneRow.ID -- cstate.State = 0 -- recordCounterState(cstate) if (oldState == "1" or oldState == 1) then fileChanged = true end end debugInfo ("end checkCounterExistence "); --else -- debugInfo ("Ignore inactive counters "); --end end debugInfo("*** Done Counter:", lookFor) end end end -------- FOR SERVICES --------------------------------- local services = xfile:find("Services") if (services ~= nil) then debugInfo ("Perform miniScan for *ALL ") pcall(doServiceScan) -- this way of index to all counters in the defined XML file --for iIndex = 1, (# xfile[1][1]) do for iIndex = 1, #services do oneRow = services[iIndex] -- this is ignoring all pre-6.3 files whose CounterObject attr. will be empty or null, ignore all these files if (oneRow.Name ~= nil) then -- depending on existence of instances, construct the string used local lookFor = oneRow.Name -- debugInfo("Service: ", lookFor) if (lookFor ~= "*ALL") then local oldState = oneRow.Active; --debugInfo(" service existing state: ", oldState); --debugInfo ("begin check serivice existence ") if (matchCounter == "1") then active = checkServiceExistence(oneRow.ID, oneRow.Name, matchCounter) else active = 1 end if (active == 1) then --debugInfo("This service exists") oneRow.Active = 1 if (oldState == "0" or oldState == 0 ) then debugInfo(neRow.Name, " used to non-exist and now exist"); fileChanged = true end else --debugInfo("This service is inactive") oneRow.Active = 0 -- local cstate = {} -- cstate.CounterID = oneRow.ID -- cstate.State = 0 -- recordCounterState(cstate) if (oldState == "1" or oldState == 1) then debugInfo(oneRow.Name, " used to exist and now non-exist"); fileChanged = true end end --debugInfo ("end checkServiceExistence "); end --debugInfo("*** Done Service:", lookFor) end end end if (fileChanged) then debugInfo ("file changed, we are saving a new copy of monitorset file"); local savefile = string.match(name, "(KMON$%d+.xml)") xml.save(xfile, eventDirectory..savefile) end end end ---------------------------------------------------------------------------------------------------------------- -- function to see if a given counterobject, counter and instance is in the counters defined in the XML file -- NOTE: this is only called during miniScan for instance *ALL, which implies all instances should already -- exists in the set XML -------------------------------------------------------------------------------------------------------------- function seeIfInstanceThere(counterObject, counter, counterInstance, counterTable) local hardDisk = string.find(counterInstance, "HarddiskVolume") if (hardDisk ~= nil) then return true end local bFound = false debugInfo("If the instance there?", counterInstance) for iIndex = 1, (# counterTable) do oneRow = counterTable[iIndex] if (oneRow.CounterObject == counterObject and oneRow.Counter == counter and oneRow.CounterInstance == counterInstance) then bFound = true break end end return bFound end -- Scan for all services function doServiceScan() local serviceChanged = true local allServicesFilePath = processDirectory.."miniScanForAllServices.txt" local allServicesFilePath = processDirectory.."miniScanForAllServices.txt" local allServicesFileEventsPath = eventDirectory.."miniScanForAllServices.txt" local allServicesFilePathNew = processDirectory.."miniScanForAllServices_new.txt" if file_exists(allServicesFilePathNew) then os.remove (allServicesFilePathNew) end if file_exists(allServicesFilePath) then os.execute ("sc query type= service state= all| findstr /B /C:\"SERVICE_NAME:\" >> "..[["]]..allServicesFilePathNew..[["]]) -- compare the content local lastfile = io.open(allServicesFilePath,"r") local lastcontent = lastfile.read(lastfile, "*a") io.close(lastfile) local newfile = io.open(allServicesFilePathNew,"r") local newcontent = newfile.read(newfile, "*a") io.close(newfile) if (lastcontent == newcontent) then serviceChanged = false debugInfo("No new services since last scan", "") os.remove (allServicesFilePathNew) else -- over serviceChanged = true debugInfo("New services found since last scan!", "") os.remove (allServicesFilePath) os.rename (allServicesFilePathNew, allServicesFilePath) os.execute ("copy "..[["]]..allServicesFilePath..[["]].. " " ..[["]]..allServicesFileEventsPath..[["]]) end else os.execute ("sc query type= service state= all| findstr /B /C:\"SERVICE_NAME:\" >> "..[["]]..allServicesFilePath..[["]]) os.execute ("copy "..[["]]..allServicesFilePath..[["]].. " " ..[["]]..allServicesFileEventsPath..[["]]) end end ---------------------------------------------------------------------------------------------- -- MiniScan is done for any counterobject that includes *ALL as instances -- This is necessary to make sure all new instances since last deployment are discovered and included in the monitoring ---------------------------------------------------------------------------------------------- function doMiniScan(counterObject, counter, setFile) local typeperfOutput = processDirectory.."miniScanForObject"..counterObject; --run the commmand and produce the file that will include all instances for given counterobject local theCommand = string.format(os.getenv("windir").."\\system32\\"..'typeperf -qx "%s" -o "%s" -y ', counterObject , typeperfOutput) debugInfo("Executing command:") debugInfo(theCommand) os.execute(theCommand) local needToUpdateData = {tag="AllMissingInstances"} -- counter data as table to be used as lookup local counterTable = xml.load(setFile) local counters = counterTable:find("Counters") if (counters~= nil) then local minifile = io.open(typeperfOutput,"r") local content = minifile.read(minifile, "*a") io.close(minifile) os.remove(typeperfOutput) -- construct the capture pattern, escape % with %% as in LUA, % is a special characters counterPattern = string.gsub(counter, "%%", "%%%%") local pattern = "\\"..counterObject.."%(([%w:_%-%.{}]+)%)\\"..counterPattern debugInfo("Looking for pattern ..", pattern) local somethingMissing = false for w in string.gmatch(content, pattern) do debugInfo("working on ",w) local row = {tag="MissingInstance"} -- check to see any of the instances in the newly found *ALL instanceExists = seeIfInstanceThere(counterObject, counter, w, counters) if (instanceExists) then debugInfo("Instance "..w, " Found") else debugInfo("Instance "..w, " Missing") row.CounterObject = counterObject row.Counter = counter row.CounterInstance = w table.insert(needToUpdateData, row) somethingMissing = true end end if (somethingMissing) then xml.save(needToUpdateData,eventDirectory.."MonitoringMissingInstance_"..counterObject..".xml") end end end function checkServiceExistence(monitorServiceId, serviceName, matchCounter) local status = 0 -- this is the same *ALL service scan result used for checking local allServicesFilePath = processDirectory.."miniScanForAllServices.txt" local file = io.open(allServicesFilePath,"r") local content = string.upper(file.read(file, "*a")) io.close(file) index = string.find(content, string.upper(serviceName), 1, true) if (index == nil) then -- the counter defined in the SET XML doesn't exist on the machine -- This status = 0 eventually becomes active = 0" in the set XML to let agent knows that to ignore such counter debugInfo(serviceName .. " Not found, ignored") status = 0 else -- see if this is: status = 1 end return status end --------------------------------------------------------------------------------------------------------------- -- function to check to see if a defined counter in the xml exists on the system -- if not exists, then, we need to create it -- if exists, then, we need to update it and restart it --------------------------------------------------------------------------------------------------------------- function checkCounterExistence (mcCounterId, counterObjectToLookFor, counterToLookFor, counterInstanceToLookFor, interval, logfilePath, matchCounter, counterObjectPrevious) local status = 0 -- there can be spaces in the path logfilePath = [["]]..logfilePath..[["]] -- if no matching, then --- **** PER design, counters always match from now on --if (matchCounter == "0" ) then -- debugInfo("BEGIN - Check counter regardless for non-matching ") -- checkDataCollector(mcCounterId, counterObjectToLookFor, counterToLookFor, counterInstanceToLookFor, interval, logfilePath) -- status = 1 -- debugInfo("END - Check counter regardless for non-matching ") --else local typeperfOutput = processDirectory.."typeperfOut.txt"; if (interval == nil) then interval = 60 end --run the commmand and produce the file if (string.format(counterObjectToLookFor) == string.format(counterObjectPrevious) and file_exists(typeperfOutput)) then -- if it's the same counter object and the previous file exists debugInfo("Previous and current Object is the same so previous typeperf file will be used.") else -- if it's not the same counter object debugInfo("Previous and current Object differs so generating new typeperf file.") local theCommand = string.format(os.getenv("windir").."\\system32\\"..'typeperf -qx "%s" -o "%s" -y ', counterObjectToLookFor , typeperfOutput) debugInfo(theCommand) os.execute (theCommand) end -- the string we are looking for lookFor = "" -- Read the file and look for the counter if counterInstanceToLookFor == "" then lookFor = string.format('\\%s\\%s', counterObjectToLookFor, counterToLookFor) else lookFor = string.format('\\%s(%s)\\%s', counterObjectToLookFor, counterInstanceToLookFor, counterToLookFor) end -- open the file and look for local file = io.open(typeperfOutput,"r") local content = file.read(file, "*a") io.close(file) if (matchCounter== "0") then debugInfo("Performing Create, Update and Start operations for counter "..mcCounterId.. " "..counterObjectToLookFor.." "..counterToLookFor.. " "..counterInstanceToLookFor) checkDataCollector(mcCounterId, counterObjectToLookFor, counterToLookFor, counterInstanceToLookFor, interval, logfilePath) status = 1 else index = string.find(content, lookFor, 1, true) if (index == nil) then -- the counter defined in the SET XML doesn't exist on the machine -- This status = 0 eventually becomes active = 0" in the set XML to let agent knows that to ignore such counter debugInfo("Matching Counter "..lookFor.." not found, ignored") debugInfo("trying to remove any invalid ones if so defined on the agent, ignore error below"); logmanRemove(mcCounterId, logfilePath); status = 0 else debugInfo("Performing Create, Update and Start operations for counter "..mcCounterId.. " "..counterObjectToLookFor.." "..counterToLookFor.. " "..counterInstanceToLookFor) checkDataCollector(mcCounterId, counterObjectToLookFor, counterToLookFor, counterInstanceToLookFor, interval, logfilePath) status = 1 end end --os.remove(typeperfOutput) -- do not remove this file any more since it will be reused when counterObjectToLookFor is the same as counterObjectPrevious --end return status end function FormatIntervalAsHHMMSS(sSeconds) local nSeconds = tonumber(sSeconds) if nSeconds == 0 then return "00:00:00"; else nHours = string.format("%02.f", math.floor(nSeconds / 3600)); nMins = string.format("%02.f", math.floor(nSeconds / 60 - (nHours * 60))); nSecs = string.format("%02.f", math.floor(nSeconds - nHours * 3600 - nMins * 60)); return nHours..":"..nMins..":"..nSecs end end function checkDataCollector(mcCounterId, counterObjectToLookFor, counterToLookFor, counterInstanceToLookFor, interval, logfilePath) interval = FormatIntervalAsHHMMSS(interval) -- Note: when used with logman command, extra " is needed to encode spaces if counterInstanceToLookFor == "" then theCounterDetail = string.format('"\\%s\\%s"', counterObjectToLookFor, counterToLookFor) else theCounterDetail = string.format('"\\%s(%s)\\%s"', counterObjectToLookFor, counterInstanceToLookFor, counterToLookFor) end local updateServer = false runningOrNot = "false" local index = "KCTR$"..mcCounterId local createCmd = "" local createCmd2 = "" local createCmd3 = "" local updateCmd = "" local stopCmd = "" local startCmd = "" if (osVersion == "6.0" or osVersion == "6.1" or osVersion == "6.2") then createCmd = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v -ow" createCmd2 = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v NNNNN -ow" createCmd3 = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v NNNNNN -ow" updateCmd = os.getenv("windir").."\\system32\\".."logman.exe update counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v -ow" stopCmd = os.getenv("windir").."\\system32\\".."logman.exe stop "..index startCmd = os.getenv("windir").."\\system32\\".."logman.exe start "..index --elseif (osVersion == "5.2") then -- createCmd = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v" -- updateCmd = os.getenv("windir").."\\system32\\".."logman.exe update counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v" -- stopCmd = os.getenv("windir").."\\system32\\".."logman.exe stop "..index -- startCmd = os.getenv("windir").."\\system32\\".."logman.exe start "..index else createCmd = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v" createCmd2 = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v NNNNN " createCmd3 = os.getenv("windir").."\\system32\\".."logman.exe create counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v NNNNNN " updateCmd = os.getenv("windir").."\\system32\\".."logman.exe update counter KCTR$"..mcCounterId .." -c " ..theCounterDetail.. " -si "..interval.." -o "..logfilePath.." -f csv --v" stopCmd = os.getenv("windir").."\\system32\\".."logman.exe stop "..index startCmd = os.getenv("windir").."\\system32\\".."logman.exe start "..index end --debugInfo(createCmd) --debugInfo(updateCmd) local event = {} event.CounterID = mcCounterId -- if the counter already exists, then, we need to make sure it's running -- try to start it once for now if (allDataCollectors["KCTR$"..mcCounterId] ~= nil) then runningOrNot = allDataCollectors["KCTR$"..mcCounterId] debugInfo("status :"..runningOrNot) if (runningOrNot ~= "Running") then debugInfo(theCounterDetail, "counter exists, but stopped") debugInfo("remove, create and start counter: " ..theCounterDetail .." ID: ".. mcCounterId) logmanRemove(mcCounterId, logfilePath); os.execute(createCmd) os.execute(createCmd2) os.execute(createCmd3) os.execute(startCmd) event.Status = 1 event.Description = "Counter existing status: Stopped, delete, create and start was performed on the counter" debugInfo(createCmd); debugInfo(createCmd2); debugInfo(createCmd3); debugInfo(startCmd); updateServer = true; else event.Status = 2 event.Description = "Counter existing status: Running, update was performed on the counter" debugInfo(theCounterDetail, "counter exists and running") debugInfo("update counter: " ..theCounterDetail .." ID: ".. mcCounterId) debugInfo(updateCmd); os.execute(updateCmd) end else event.Status = 3 event.Description = "Counter doesn't exist, create and start was performed on the counter" debugInfo(theCounterDetail, "counter doesn't exist") debugInfo("create and start counter: " ..theCounterDetail .." ID: ".. mcCounterId) debugInfo(createCmd); debugInfo(createCmd2); debugInfo(createCmd3); debugInfo(startCmd); os.execute(createCmd) os.execute(createCmd2) os.execute(createCmd3) os.execute(startCmd) updateServer = true; end if (updateServer) then recordEvent(event) end end ---------------------------------------------------------------------------------------------- -- Get the version of OS and return a OS version string -- this is needed to make sure the counter creation command is proper depdending on the OS -- Important things to remember is that typeperf and logman ---------------------------------------------------------------------------------------------- function getOSVersion (processDirectory) local osVersion = "5.0" -- See if the OS version file is there, if it's there, read out the version local osVersionFilePath = processDirectory.."OSVersion.txt" debugInfo("osVersionFilePath", osVersionFilePath); local versionFile = io.open(osVersionFilePath,"r") if versionFile ~=nil then local content = versionFile.read(versionFile,"*a") --OS Version: 6.1.7601 Service Pack 1 Build 7601 --Windows 7 6.1 --Windows Server 2008 R2 6.1 --Windows Server 2008 6.0 --Windows Vista 6.0 --Windows Server 2003 R2 5.2 --Windows Server 2003 5.2 --Windows XP 64-Bit Edition 5.2 --Windows XP 5.1 --Windows 2000 5.0 osVersion = string.gmatch(content, "OS Version:%s+(%d.%d)[%w+%p+]+") osVersion = osVersion(1) else print("Execute systeminfo") --try to create this again, the very first time or it could have failed if OS is WIN2K os.execute ("systeminfo | findstr /B /C:\"OS Name\" /C:\"OS Version\" >> "..[["]]..osVersionFilePath..[["]]) versionFile = io.open(osVersionFilePath,"r") if versionFile ~=nil then local content = versionFile.read(versionFile,"*a") osVersion = string.gmatch(content, "OS Version:%s+(%d.%d)[%w+%p+]+") osVersion = osVersion(1) end end return osVersion end -- debug info helper function debugInfo (rowtag, strOut) if (strOut == nil) then strOut = "" end if (DEBUG_MODE) then print (rowtag.." "..strOut) table.insert(processDebug, rowtag.." ".. strOut) end end -- event info helper function recordEvent(event) table.insert(processEvent, event) end --function recordCounterState(state) -- table.insert(counterState, state) --end --===================================================================================================== ----------------------------- The process logic starts here --===================================================================================================== eventFileName ="MonitoringProcessEvents.xml" --stateFileName ="MonitoringCounterStates.xml" debugFileName = "processDebug.xml" processDebug = {tag="ProcessDebug"} processEvent = {tag="ProcessEvents"} --counterState = {tag="CounterState"} osVersion = "6.0" updateServer = false; if (arg[1] == nil) then debugInfo("Parameters Error:", " Wrong Agent temp directory ") os.exit() end workingDirectory = KLua.Var.users.agentTempDir.."\\Kmonitorsets\\" --workingDirectory = arg[1].."\\Kmonitorsets\\" debugInfo("workingDirectory", workingDirectory) processDirectory = workingDirectory.."ProcessingInfo\\" debugInfo("processDirectory", processDirectory) eventDirectory = workingDirectory.."Events\\" debugInfo("eventDirectory", eventDirectory) kLogsDirectory = KLua.Var.users.agentTempDir.."\\Klogs\\" -------- make sure the directory exists, fail as it maybe, always create lfs.mkdir(processDirectory) lfs.mkdir(eventDirectory) lfs.mkdir(kLogsDirectory) lfs.mkdir(workingDirectory) debugInfo("done creating directories", "") ------------------------------------------------------------------------- ------------ semiphore file would temporarily suspend processing of this agent ----------------- NOTE: processStop.txt in processing directory would permanentally disable processing local semaFilePath = processDirectory.."processStop.txt" local semaStop = file_exists(semaFilePath) debugInfo("processStop:", tostring(semaStop)) ------------ self clean file would enable self-cleaning processing of this agent ------------DO THIS ******* ONLY, ONLY ************ IF a single agent is enabled for Kaseya Monitoring local cleanFilePath = processDirectory.."selfclean.txt" local semaClean = file_exists(cleanFilePath) if (semaClean) then os.remove(cleanFilePath); end debugInfo("semaClean:", tostring(semaClean)) ------- Process ONLY if the stopping semaphone file doesn't exist if semaStop== false then -- OS Version --osVersion = getOSVersion(processDirectory) --debugInfo("OS", osVersion) allDataCollectors = {} ------ Query for all defined counters and remember all the counters------------ allCountersPath = processDirectory.. "allCounters.txt" os.execute (os.getenv("windir").."\\system32\\".."logman -query >> "..[["]]..allCountersPath..[["]]) debugInfo("All current defined counters:", allCountersPath) local file = io.open(allCountersPath) local content = file.read(file,"*a") local lookFor = "(KCTR%$%w+)%s+Counter%s+(%a+)" for k, v in string.gmatch(content, lookFor) do debugInfo("CurrentCounter", k.."\tStatus:" ..v) -- and Remember all the counters we know defined and their status allDataCollectors[k] = v end -- Close the file and remove the temp file io.close(file) -- Now, let's process the cleaning work -- This is the cleanup, but can't know multiple agents situation if (semaClean == true) then processCleanMonsetFile(workingDirectory.."KCleanCounters.xml", allCountersPath) end --Remove the all counter lists os.remove(allCountersPath) debugInfo("Processing all monitorset files :", "") ----------------Now we all known coutners defined stored in allDataCollectors, Process all monitorset files --Process all removed files first for name in lfs.dir(workingDirectory) do s = string.find(name, "^KRemove%$[%d+]") if(name ~= "." and name ~= ".." and s ~= nil) then local path = workingDirectory..name local eventPath = eventDirectory..name debugInfo("Begin --------------------------", name) processRemoveMonsetFile(path, eventPath) debugInfo("Done --------------------------", name) end end for name in lfs.dir(workingDirectory) do s = string.find(name, "^KMON%$[%d+]") if(name ~= "." and name ~= ".." and s ~= nil) then local path = workingDirectory..name debugInfo("Begin --------------------------", name) pcall(processMonsetFile,path) debugInfo("Done --------------------------", name) end end else debugInfo("ProcessStop.txt:", "No Processing. Remove the file to process" ) end --Always save xml.save(processDebug,processDirectory..debugFileName) -- if state is not empty, then save, not needed, as the whole changed KMON$XML is fetched back up --if (#counterState > 0) then -- xml.save(counterState,eventDirectory..stateFileName) --end -- do this only if anything is changed on the agent if (#processEvent > 0) then xml.save(processEvent,eventDirectory..eventFileName) end