From 72afef93bdb2a2982cf8588a3e735d2cf117d6b6 Mon Sep 17 00:00:00 2001 From: Wouter R Date: Fri, 16 Aug 2013 20:03:53 +0200 Subject: [PATCH] Add d3dapi/info/logfiles API call to obtain a tgz file containing the most important log data. --- src/rest/api/api_info.lua | 70 ++++++++++++++++++++++++++++++++++++++- src/rest/response.lua | 37 ++++++++++++++++++--- 2 files changed, 102 insertions(+), 5 deletions(-) diff --git a/src/rest/api/api_info.lua b/src/rest/api/api_info.lua index 277348c..44662ac 100644 --- a/src/rest/api/api_info.lua +++ b/src/rest/api/api_info.lua @@ -1,8 +1,25 @@ +local lfs = require('lfs') + +local TMP_DIR = '/tmp' +local LOG_COLLECT_DIRNAME = 'wifibox-logs' +local LOG_COLLECT_DIR = TMP_DIR .. '/' .. LOG_COLLECT_DIRNAME +local WIFIBOX_LOG_FILENAME = 'wifibox.log' +local WIFIBOX_LOG_FILE = TMP_DIR .. '/' .. WIFIBOX_LOG_FILENAME +local ULTIFI_PATH = '/tmp/UltiFi' +local SYSLOG_FILENAME = 'syslog' +local ULTIFI_LOG_FILENAME = 'server.log' +local LOG_COLLECT_ARCHIVE_FILENAME = LOG_COLLECT_DIRNAME .. '.tgz' +local LOG_COLLECT_ARCHIVE_FILE = TMP_DIR .. '/' .. LOG_COLLECT_ARCHIVE_FILENAME + +local function redirectedExecute(cmd) + return os.execute(cmd .. " > /dev/null 2>&1") +end + + local M = { isApi = true } - function M._global(request, response) response:setSuccess() end @@ -16,4 +33,55 @@ function M.firmware(request, response) -- upgradable end +-- TODO: redirect stdout+stderr; handle errors +function M.logfiles(request, response) + local rv,msg = lfs.mkdir(LOG_COLLECT_DIR) + local rv,msg = lfs.chdir(TMP_DIR) + + + --[[ create temporary files ]]-- + + local rv,sig,code = redirectedExecute('cp ' .. WIFIBOX_LOG_FILE .. ' ' .. LOG_COLLECT_DIR) + + local rv,sig,code = os.execute('logread > ' .. LOG_COLLECT_DIR .. '/' .. SYSLOG_FILENAME) + + for file in lfs.dir(ULTIFI_PATH) do + if file ~= '.' and file ~= '..' then + local srcLogFile = ULTIFI_PATH .. '/' .. file .. '/' .. ULTIFI_LOG_FILENAME + local tgtLogFile = LOG_COLLECT_DIR .. '/' .. file .. '-' .. ULTIFI_LOG_FILENAME + local rv,sig,code = redirectedExecute('cp ' .. srcLogFile .. ' ' .. tgtLogFile) + end + end + + local rv,sig,code = redirectedExecute('tar czf ' .. LOG_COLLECT_ARCHIVE_FILE .. ' ' .. LOG_COLLECT_DIRNAME) --returns 0 success, 1 error + + + --[[ add response content ]]-- + + local rv,msg = response:setBinaryFileData(LOG_COLLECT_ARCHIVE_FILE, LOG_COLLECT_ARCHIVE_FILENAME, 'application/x-compressed') + if not rv then + response:setError("could not set binary data from file '" .. LOG_COLLECT_ARCHIVE_FILE .. "' (" .. msg .. ")") + else + response:setSuccess() + end + + + --[[ remove temporary files ]]-- + + for file in lfs.dir(ULTIFI_PATH) do + if file ~= '.' and file ~= '..' then + local tgtLogFile = LOG_COLLECT_DIR .. '/' .. file .. '-' .. ULTIFI_LOG_FILENAME + local rv,sig,code = redirectedExecute('rm ' .. tgtLogFile) + end + end + + local rv,sig,code = redirectedExecute('rm ' .. LOG_COLLECT_DIR .. '/' .. WIFIBOX_LOG_FILENAME) + + local rv,sig,code = redirectedExecute('rm ' .. LOG_COLLECT_DIR .. '/' .. SYSLOG_FILENAME) + + local rv,msg = lfs.rmdir(LOG_COLLECT_DIR) + + local rv,sig,code = redirectedExecute('rm ' .. LOG_COLLECT_ARCHIVE_FILE) +end + return M diff --git a/src/rest/response.lua b/src/rest/response.lua index 4e7b8cf..04d249c 100644 --- a/src/rest/response.lua +++ b/src/rest/response.lua @@ -8,6 +8,11 @@ M.__index = M local REQUEST_ID_ARGUMENT = 'rq_id' M.httpStatusCode, M.httpStatusText, M.contentType = nil, nil, nil +M.binaryData, M.binarySavename = nil, nil + +local function printHeaderLine(headerType, headerValue) + io.write(headerType .. ": " .. headerValue .. "\r\n") +end setmetatable(M, { @@ -68,6 +73,7 @@ end --(e.g.: response:addData('data', {f1=3, f2='x'})) function M:addData(k, v) self.body.data[k] = v + self.binaryData = nil end function M:apiURL(mod, func) @@ -81,11 +87,34 @@ function M:serializeAsJson() end function M:send() - io.write("Status: " .. self.httpStatusCode .. " " .. self.httpStatusText .. "\r\n") - io.write("Content-type: " .. self.contentType .. "\r\n") - io.write("Access-Control-Allow-Origin: *\r\n\r\n") + printHeaderLine("Status", self.httpStatusCode .. " " .. self.httpStatusText) + printHeaderLine("Content-type", self.contentType) + printHeaderLine("Access-Control-Allow-Origin", "*") - print(self:serializeAsJson()) + if self.binaryData == nil then + io.write("\r\n") + print(self:serializeAsJson()) + else + printHeaderLine("content-disposition", "attachment;filename=" .. self.binarySavename) + io.write("\r\n") + io.write(self.binaryData) + end +end + +function M:setBinaryFileData(rFile, saveName, contentType) + if type(rFile) ~= 'string' or rFile:len() == 0 then return false end + + local f,msg = io.open(rFile, "rb") + + if not f then return nil,msg end + + self.binaryData = f:read("*all") + f:close() + + self.binarySavename = saveName + self:setContentType(contentType) + + return true end return M