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>
LM User
·3 years ago@Stuart Weenig I checked your permissions, you should be able to edit, no time restrictions, LMK if it’s just this post, or if you are having issues editing all your posts, I can get a ticket logged,
I’ve had issues before editing my replies, but not my posts.
@Stuart Weenig I checked your permissions, you should be able to edit, no time restrictions, LMK if it’s just this post, or if you are having issues editing all your posts, I can get a ticket logged,
LM User
·3 years agoI had to add a .trim() to the wildvalue during discovery to make sure there were not phantom spaces. Once I fixed that, the collection (which was fine the whole time) started working just fine.
You can drop your version into text-compare.com to see how it differs from mine, which is now running in my portal. I decided to put it up in github because of some odd errors when trying to edit my previous reply. (@A11ey do you know why I can’t edit my previous reply? I’d like to strike out the code and link to the github repo)
Shack
OP3 years agoWhat were your additional changes? I’m still not getting the response.
As far as values - 4 so far.
Off
Green
Yellow
Red
I’m going to have to read a bit more but yellow can mean “passive” for HA yet for temp it’s “outside of normal range” which could technically be bad. Red is definitely bad.
LM User
·3 years agoUpdate: needed to trim some non-printable/invisible characters off the wildvalue. I’ve updated the above scripts. It’s working in my portal now against all my palos. If you find out what other values the LEDs can have (besides Off and Green), let me know so I can update it. Or if you have a link to the api docs where this is detailed, i might be able to pull it out of there.
Shack
OP3 years agoOk, 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):
Here’s the collection script:
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.
I am seeing the same response in my env.
Shack
OP3 years agoWhat got me to this was we had a failed drive on one of ours and I’m not even sure how it was discovered and no way of telling how long it had been failed. Using chassis.led’s seemed like a logical all inclusive method to grab this sort of thing.
Meanwhile you could use a filter like this <show><system><state><filter>env.s0.mp.raid.disk1</filter></state></system></show> and go after the alarm status of disk 1.
Disk 0 would be <show><system><state><filter>env.s0.mp.raid.disk0</filter></state></system></show>
The response from our device with a bad drive looked like this:
env.s0.mp.raid.disk1-status: { 'alarm': True, 'avg': False, 'desc': Disk Log2 status, 'min': 1, }
Chassis Led’s seem to be color driven however for the disk alerts they look to be using True/False.
You can run <show><system><state></state></system></show> and get back the whole big response if you are interested in seeing everything it returns. It’s a lot of information though.
I’m going to try out what you have done on my device and see what it returns.
LM User
·3 years agoOk, 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
Here’s the collection script:
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.
LM User
·3 years agoYou probably don’t need this to be a multi-instance DS. You don’t need discovery. Just make it a SCRIPT DS that’s single instance. Then you only need a collection script that would look like this:
I don’t know the possible values of the LEDs, but you’d add them into the status_map and assign them a value.
LM User
·3 years agoThis could be very very simple, or just simple.
Ignore the rest of this response if you’re trying to add this instance to discovery of instances in an existing datasource, as that’s a different thing and not recommended. But it doesn’t seem that’s what you’re doing.
Option A:
Option B:
Shack
OP3 years agoRight now I’m working on the discovery portion and haven’t figured out how I want the collection part just yet. My discovery hopes are for an instance named chassis leds to be created for now.
LM User
·3 years agoIf I’m following right, your response object after you use the XmlSlurper on it should return a Groovy Map (similar to Python Dictionary). So you should be able to loop over it without using RegEx:
Is this your collection script or the discovery script? I’m not familiar with the original so the output will depend on which part you’re currently building.
Shack
OP3 years agoMade a little progress. Here’s where I’m at but now I’m stuck on getting the response trimmed out with my regex. You can see the first println and the second(which shows the actual output). What am I doing wrong that I cannot println just “chassis.leds”?
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) {
response = new XmlSlurper().parseText(getRequestConn.content.text)
def instance = (response=~/(^(.+?):)/)
println "${instance}##${instance}";
println response
}
return 0