You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.4 KiB
174 lines
5.4 KiB
# Version 4.0
|
|
#
|
|
|
|
from splunk.clilib import cli_common, control_api
|
|
from splunk.appserver import Util, Template, html, SearchFormatter, SearchAgent
|
|
import logging as logger
|
|
import os, traceback
|
|
from defusedxml.cElementTree import fromstring as safe_fromstring
|
|
|
|
|
|
def get(requestObject) :
|
|
requestArgs = _flattenRequestArgs(requestObject)
|
|
|
|
requestObject.setHeader('content-type', 'text/html')
|
|
t = _getTemplate("surrounding_events.html", requestArgs)
|
|
|
|
|
|
searchCommand = _getSearchCommand(requestArgs)
|
|
|
|
#tack the extra output clause back onto q
|
|
searchCommand += "| outputxml format::raw maxlines::10000"
|
|
|
|
requestArgs["q"] = searchCommand
|
|
|
|
# get the proper search agent
|
|
searchAgent = SearchAgent.Factory(requestArgs, requestObject.getSession())
|
|
|
|
# return the output from search agent
|
|
agentResponse = searchAgent.run()
|
|
|
|
if( searchAgent.messages ):
|
|
messagesBlock = html.HTMLList()
|
|
for message in searchAgent.messages:
|
|
messagesBlock.append( html.Raw( message["text"] ) )
|
|
messagesBlock.append( html.br() )
|
|
messagesBlock.append( html.br() )
|
|
t.messages = messagesBlock
|
|
else:
|
|
t.messages = html.Raw("")
|
|
|
|
parsedResponse = safe_fromstring(agentResponse)
|
|
|
|
eventsBlock = html.HTMLList()
|
|
|
|
cdIndex = ""
|
|
decIndex = ""
|
|
|
|
for rNode in parsedResponse.findall(".//cols"):
|
|
for cNode in rNode.findall(".//col"):
|
|
if cNode.text == "_decoration":
|
|
decIndex = cNode.attrib["cd"]
|
|
elif cNode.text == "_cd":
|
|
cdIndex = cNode.attrib["cd"]
|
|
|
|
for rNode in parsedResponse.findall(".//r") :
|
|
thisEventId = "0:0000000"
|
|
thisDecoration = ""
|
|
try :
|
|
for mNode in rNode.findall(".//m") :
|
|
if mNode.attrib["col"] == cdIndex :
|
|
thisEventId = mNode.text
|
|
elif mNode.attrib["col"] == decIndex :
|
|
thisDecoration = mNode.text
|
|
|
|
except Exception as e:
|
|
logger.debug("could not get thisEventId")
|
|
traceback.print_exc()
|
|
|
|
|
|
for vNode in rNode.findall(".//v") :
|
|
logger.debug("****" * 20)
|
|
logger.debug(vNode.text)
|
|
preElement = html.pre()[vNode.text]
|
|
|
|
# the class is needed for the CSS highlighting, but an ID is also used by the JS, for the scroll-to behaviour.
|
|
thisClass = "resultRow " + thisDecoration
|
|
thisId = ""
|
|
if (thisEventId == requestArgs["eventId"]) :
|
|
thisClass += " selectedRow"
|
|
thisId = "selectedItem"
|
|
|
|
innerDiv = html.div(class_=thisClass, id="events" + thisEventId)[preElement]
|
|
resultRowDiv = html.div(id=thisId)[innerDiv]
|
|
|
|
eventsBlock.append(resultRowDiv)
|
|
|
|
t.events = eventsBlock
|
|
|
|
if "server" not in requestArgs:
|
|
t.server = ""
|
|
|
|
t.run(requestObject)
|
|
return ""
|
|
|
|
|
|
|
|
|
|
def export(requestObject) :
|
|
|
|
requestArgs = _flattenRequestArgs(requestObject)
|
|
searchCommand = _getSearchCommand(requestArgs)
|
|
|
|
requestObject.setHeader("Content-type", "text/plain")
|
|
requestObject.setHeader("Content-disposition", "attachment; filename=source.txt;")
|
|
|
|
#tack the extra output clause back onto q
|
|
searchCommand += "| outputtext"
|
|
requestArgs["q"] = searchCommand
|
|
|
|
# get the proper search agent
|
|
searchAgent = SearchAgent.Factory(requestArgs, requestObject.getSession())
|
|
|
|
# return the output from search agent
|
|
agentResponse = searchAgent.run()
|
|
|
|
parsedResponse = safe_fromstring(agentResponse)
|
|
|
|
try :
|
|
resultsNode = parsedResponse.findall(".//results")[0]
|
|
return resultsNode.text
|
|
|
|
except Exception as e:
|
|
logger.error("Show source did not return expected results. ")
|
|
return agentResponse
|
|
|
|
##################
|
|
# Internal functions that arent intended to be accessed via the endpoints.
|
|
##################
|
|
|
|
def _getTemplate(fileNameStr,requestArgs) :
|
|
path = [os.environ["SPLUNK_HOME"]]
|
|
path.append("share/splunk")
|
|
try :
|
|
frontEndName = cli_common.confSettings["web"]["settings"]
|
|
if not frontend_name: frontend_name = 'oxiclean'
|
|
except Exception as e:
|
|
frontend_name = 'oxiclean'
|
|
frontend_dirname = 'search_' + frontend_name
|
|
path.append(frontend_dirname);
|
|
path.append('static/html')
|
|
path.append(fileNameStr)
|
|
|
|
t = Template.Template("/".join(path))
|
|
for key in requestArgs :
|
|
t.__setattr__(key, requestArgs[key])
|
|
return t
|
|
|
|
|
|
def _getSearchCommand(requestArgs) :
|
|
searchCommand = ["|"]
|
|
remote = False
|
|
if "server" in requestArgs:
|
|
remote = True
|
|
searchCommand.append( "remote " + requestArgs["server"] + " [ ");
|
|
searchCommand.append("surrounding")
|
|
searchCommand.append("id::" + requestArgs["eventId"])
|
|
searchCommand.append("index::" + requestArgs["eventIndex"])
|
|
searchCommand.append("searchkeys=\"" + requestArgs["q"] + "\"")
|
|
searchCommand.append("readlevel::2")
|
|
searchCommand.append("maxresults::" + requestArgs["num"])
|
|
searchCommand.append("timeBefore::60")
|
|
searchCommand.append("timeAfter::60")
|
|
if( remote ):
|
|
searchCommand.append( " ]" )
|
|
|
|
return " ".join(searchCommand)
|
|
|
|
def _flattenRequestArgs(requestObject) :
|
|
# generate flattened request args dict
|
|
requestArgs = {}
|
|
for key in requestObject.args:
|
|
requestArgs[key] = requestObject.args[key][0]
|
|
return requestArgs
|