I've written a small script for Zabbix to check the status of our ESXi Hosts. The request needs to be authenticated, so I went for this process:
- Read auth token from file
- If file does not exist, authenticate and store token into file
- Run request to get the information
- If I get permission denied, authenticate, store the token into file and try again
Is there a better way to handle this? It bothers me a little to have the get_host_state()
call twice, but placing the handling of the permission error into the function would make it recursive, which would then need additional parameters to prevent an endless loop and which would make it more complex.
Could the functions themselves be improved?
Notes:
- I'm aware that there are existing python modules to access the API, but I want to avoid the hassle and overhead of setting up a virtualenv and installing countless python modules on the Zabbix server for a simple check
- I disabled the traceback on purpose because I get the first line of the output of the script directly in Zabbix when an error occurs and this way I see directly the error instead of the pretty useless first line of the stacktrace.
The response from the API is json, which is then parsed and handled in Zabbix.
full script:
import requests
import sys
vc_url = "vcenter.example.com"
vc_user = "[email protected]"
vc_password = "aHR0cDovL2JpdC5seS8xVHFjd243Cg=="
auth_store = "/tmp/zbx_esxi_connstate_auth"
esx_name = sys.argv[1]
session_id = ''
sys.tracebacklimit = 0
def vc_auth():
response = requests.post(f"https://{vc_url}/api/session", auth=(vc_user, vc_password))
if response.ok:
session_id = response.json()
with open(auth_store, "w") as file:
file.write(session_id)
return session_id
else:
raise PermissionError("Unable to retrieve a session ID.")
def read_auth():
try:
with open(auth_store, "r") as file:
session_id = file.read()
return session_id
except FileNotFoundError:
vc_auth()
def get_host_state():
response = requests.get(f"https://{vc_url}/api/vcenter/host?names={esx_name}", headers={"vmware-api-session-id": session_id})
if response.status_code == 401:
raise PermissionError("Authentication required.")
if response.ok:
print(f"{response.text}")
else:
raise ValueError(response.text)
session_id = read_auth()
try:
get_host_state()
except PermissionError:
session_id = vc_auth()
get_host_state()
Here is the response from the API for the authentication request:
HTTP/2 201
date: Thu, 15 Sep 2022 13:28:26 GMT
vmware-api-session-id: 39efaf9c1c0ababc005ce63795b773bc
content-type: application/json
x-envoy-upstream-service-time: 169
server: envoy
"39efaf9c1c0ababc005ce63795b773bc"