Arista Campus Switch Power Supply State
We recently discovered that Arista Campus switches are either just not populating the OID for Power Supply states, or are using a different one, so in my API first approach to monitoring I decided to utilize the Arista EOS API to grab the power supply data, below are the discovery and collection scripts along with some of the key field for a Data source.
You will notice I am using the Model number to identify the Arista campus switches using an if not statement "if ( !(model.startsWith("CCS-")))" which will drop all the DC switches out of the script.
As always appreciate any feedback and ways to improve on these things. Have a great day.
Note: This is obviously shared on a best efforts basis, but we are using this across all of our campus switches and it works great (We found 3 on top of the one we knew had a failed PSU that had issues).
Applies to: hasCategory("Arista")
Description:
This will check the state of the power supply and return the following.
1 = Ok
0 = Down
This replaces the Arista SNMP PSU as this returns a null value for the campus switches.
Discovery Script:
/*
Script Name: Campus Power Supply Discovery
*/
import com.santaba.agent.groovyapi.http.*;
import com.santaba.agent.util.Settings
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
// Gather host statistics
username = hostProps.get("ssh.user");
password = hostProps.get("ssh.pass");
host = hostProps.get("auto.network.names");
model = hostProps.get("auto.endpoint.model")
vendor = hostProps.get("auto.endpoint.manufacturer")
//Only need to discove the devices if the vendor is Arista Networks
if ( !(vendor = "Arista Networks"))
{
println "Do not need to discover as not an Arista Device"
return(0)
}
//Now we need to check if the model is one of these specific models if it is then fine
if ( !(model.startsWith("CCS-")))
{
println "Not a Campus Switch"
return(0)
}
//Build Authentication JSON to send to switch
def authJson = JsonOutput.toJson([username:username,password:password]);
//Build URL
url = "https://"+host+"/login";
// Make the call
httpClient = Client.open(host, 443);
def response = httpClient.post(url, authJson,["Content-Type":"application/json"]);
if ( !(httpClient.getStatusCode() =~ /200/))
{
println "Failed to retrieve data "+httpClient.getStatusCode
return(1)
}
//Get Session data so we can extract the session string
String sessionData = httpClient.getHeader("Set-Cookie");
sessionData.substring(sessionData.lastIndexOf("Session=")+1,sessionData.length());
// Remove everything including the ; after the semiColon in session Data
def firstPass = sessionData.split(';')[0];
// Remove everything before and including the = this will leave you with the session data.
def session = firstPass.split('=')[1];
// Now we can gather the data to do this we need to build the command JSON output, URL and Header
def GetStatus = JsonOutput.toJson([jsonrpc: "2.0",method: "runCmds",params: ["version": 1,cmds: [ "show environment power" ],format: "json"],"id": "1"])
def powerUrl = "https://"+host+"/command-api";
def powerHeader = ["Cookie":session,"Content-Type":"application/json"]
// Now we can retrieve the data.
//httpClient = Client.open (host,443)
def powerData = httpClient.post(powerUrl, GetStatus ,powerHeader);
if ( !(httpClient.getStatusCode() =~ /200/))
{
println "Failed to retrieve data "+httpClient.getStatusCode
return 1
}
String powerContent = httpClient.getResponseBody()
def powerTable = new JsonSlurper().parseText(powerContent)
def encoded_instance_props_array = []
def wildvalue = ""
def wildalias = ""
def description = ""
//println powerTable
powerTable.result[0].powerSupplies.each { psuNo,powerSupply ->
wildvalue = "Power_Supply_"+psuNo
wildalias = "${wildvalue}:${powerSupply.modelName}"
description = "${wildvalue}/${powerSupply.modelName}"
def instance_props = [
"auto.power_suppLy": "Power Supply " + psuNo,
"auto.power_model_name": powerSupply.modelName
]
encoded_instance_props_array = instance_props.collect() { property, value ->
URLEncoder.encode(property.toString()) + "=" + URLEncoder.encode(value.toString())
}
println "${wildvalue}##${wildalias}##${description}####${encoded_instance_props_array.join("&")}"
}
return 0Collection Script:
/*
Script Name: Campus Power Supply Collection
*/
import com.santaba.agent.groovyapi.http.*;
import com.santaba.agent.util.Settings
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
// Gather host statistics
username = hostProps.get("ssh.user");
password = hostProps.get("ssh.pass");
host = hostProps.get("auto.network.names");
model = hostProps.get("auto.endpoint.model")
vendor = hostProps.get("auto.endpoint.manufacturer")
//Only need to discove the devices if the vendor is Arista Networks
if ( !(vendor = "Arista Networks"))
{
println "Do not need to discover as not an Arista Device"
return(0)
}
//Now we need to check if the model is one of these specific models if it is then fine
if ( !(model.startsWith("CCS-")))
{
println "Not a Campus Switch"
return(0)
}
//Build Authentication JSON to send to switch
def authJson = JsonOutput.toJson([username:username,password:password]);
//Build URL
url = "https://"+host+"/login";
// Make the call
httpClient = Client.open(host, 443);
def response = httpClient.post(url, authJson,["Content-Type":"application/json"]);
if ( !(httpClient.getStatusCode() =~ /200/))
{
println "Failed to retrieve data "+httpClient.getStatusCode
return(1)
}
//Get Session data so we can extract the session string
String sessionData = httpClient.getHeader("Set-Cookie");
sessionData.substring(sessionData.lastIndexOf("Session=")+1,sessionData.length());
// Remove everything including the ; after the semiColon in session Data
def firstPass = sessionData.split(';')[0];
// Remove everything before and including the = this will leave you with the session data.
def session = firstPass.split('=')[1];
// Now we can gather the data to do this we need to build the command JSON output, URL and Header
def GetStatus = JsonOutput.toJson([jsonrpc: "2.0",method: "runCmds",params: ["version": 1,cmds: [ "show environment power" ],format: "json"],"id": "1"])
def powerUrl = "https://"+host+"/command-api";
def powerHeader = ["Cookie":session,"Content-Type":"application/json"]
// Now we can retrieve the data.
//httpClient = Client.open (host,443)
def powerData = httpClient.post(powerUrl, GetStatus ,powerHeader);
if ( !(httpClient.getStatusCode() =~ /200/))
{
println "Failed to retrieve data "+httpClient.getStatusCode
return 1
}
String powerContent = httpClient.getResponseBody()
def powerTable = new JsonSlurper().parseText(powerContent)
def encoded_instance_props_array = []
def wildvalue = ""
def wildalias = ""
def description = ""
powerTable.result[0].powerSupplies.each { psuNo,powerSupply ->
wildvalue = "Power_Supply_"+psuNo
wildalias = "Power_Supply_"+psuNo+":${powerSupply.modelName}"
psuRawState = "${powerSupply.state}"
if (psuRawState == "ok") {
psuState = 1
}
else {
psuState = 0
}
println "${wildvalue}.psuState=${psuState}"
}
return 0
I understand that part but not why you wouldn't just put it in the appliesto?
hasCategory("Arista") && startsWith(auto.endpoint.model,"CCS")