Palo Alto XML Response Help
I am interested in improving some of the Palo Alto monitoring and would like to create a datasource that looks at the chassis led’s for a particular alarm status. Using the XML API explorer the command is this:
<show><system><state><filter>chassis.leds</filter></state></system></show>
The response is below and without using the filter parameter the result body is a giant mess of information.
I’ve taken an existing ds, cloned it but my scripting knowledge of xmlslurper, parsetext and such is failing to discover anything.
Also the response below is not in the typical format the output of the other PA datasources have with regards to slots etc.. so I’m stuck on the output part of my script and it doesn’t discover anything. What I want is an instance named chassis.leds and then data from a couple of the values below.
Once I get this working I would likely create another DS that checks the status of the disk RAID configuration.
How would you write the output?
<response status="success">
<result>
<![CDATA[ chassis.leds: { 'alarm': Off, 'fans': Off, 'ha': Off, 'log': Off, 'service': Off, 'status': Green, 'temp': Green, } ]]>
</result>
</response>
- Anonymous2 years ago
Ok, this piqued my interest so i tried throwing it against one of my palos. I’m not groovy enough to understand how to work with that response object. Instead, I chose the quick/dirty route of converting to a string and parsing from there. I also now better understand the data, so I retract my original advise of making this single instance and advise instead to make it multi-instance with one instance for each LED (this may have been what you originally meant and I totally misunderstood).
Anyway, here’s the discovery script that’s now working in my environment (again, I didn’t do this the groovy way):
Updated/working script here: https://github.com/sweenig/lm/tree/main/Palo%20Chassis%20LEDs
def host = hostProps.get("system.hostname")
def port = hostProps.get("paloalto.port")?: 443
def apikey = hostProps.get("paloalto.apikey.pass")?.trim()
if (apikey == null) {println("No paloalto.apikey.pass set");return 1}
def response
def command = URLEncoder.encode("<show><system><state><filter>chassis.leds</filter></state></system></show>", "UTF-8")
def url = "https://${host}:$port/api/?type=op&key=${apikey}&cmd=${command}"
def getRequestConn = url.toURL().openConnection()
if (getRequestConn.responseCode == 200) {
body = getRequestConn.content.text
response = new XmlSlurper().parseText(body)
data = response.toString()
data.tokenize("{,}").each{
kv = it.tokenize(":")
if ((it.trim() != "chassis.leds:") && (kv.size() > 1)){
wildvalue = kv[0].replaceAll('\'','')
println("${wildvalue}##${wildvalue}")
}
}
return 0
} else {return 2}Here’s the collection script:
def host = hostProps.get("system.hostname")
def port = hostProps.get("paloalto.port")?: 443
def apikey = hostProps.get("paloalto.apikey.pass")?.trim()
if (apikey == null) {println("No paloalto.apikey.pass set");return 1}
status_map = [
"Off": 0,
"Green": 1,
"AnotherColor": 2,
"YetAnother": 3,
"AndAnother": 4
]
def response
def command = URLEncoder.encode("<show><system><state><filter>chassis.leds</filter></state></system></show>", "UTF-8")
def url = "https://${host}:$port/api/?type=op&key=${apikey}&cmd=${command}"
def getRequestConn = url.toURL().openConnection()
if (getRequestConn.responseCode == 200) {
body = getRequestConn.content.text
response = new XmlSlurper().parseText(body)
data = response.toString()
data.tokenize("{,}").each{
kv = it.tokenize(":")
if ((it.trim() != "chassis.leds:") && (kv.size() > 1)){
println("${kv[0].replaceAll('\'','')}.status: ${status_map[kv[1].trim()]}")
}
}
return 0
} else {return 2}And the datapoint looks like this:
multi-line key-value pairs: ##WILDVALUE##.status
For some reason (maybe new bug in v186) the script output has the right content but LM’s not picking it up:
service.status is definitely in the output, so i’m befuddled. Support chat here I come.