Open Neo914 opened 2 months ago
For information I use the EMC Unity REST-API v3 template
zabbix_export: version: '6.0' date: '2024-07-09T13:02:02Z' groups:
uuid: 482e80466d694a7e9dffcf708d029e2f template: 'EMC Unity REST-API v3' name: 'EMC Unity REST-API v3' description: |
Tested on Unity 600
Python-script to get metrics from EMC Unity Storage. Script uses REST-API interface.
This script get next metrics:
BBU, Disk, Disk Array Enclosure, Disk Processor Enclosure, FAN, I/O Module, LCC, Lun, Memory Module, Pool, PortEth, PortFibreChannel, PortSAS, PSU, SSC, SSD, Storage Processors, Uncommitted Port.
groups:
and the script unity_get_state.py
import os import time import argparse import sys import json import subprocess import logging import logging.handlers import requests import urllib3
from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
LOG_FILENAME = "/tmp/unity_state.log" unity_logger = logging.getLogger("unity_logger") unity_logger.setLevel(logging.INFO)
unity_handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=1024*1024, backupCount=5) unity_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
unity_handler.setFormatter(unity_formatter)
unity_logger.addHandler(unity_handler)
def api_connect(api_user, api_password, api_ip, api_port): api_login_url = "https://{0}:{1}/api/types/loginSessionInfo".format(api_ip, api_port) session_unity = requests.Session() session_unity.auth = (api_user, api_password) session_unity.headers = {'X-EMC-REST-CLIENT': 'true', 'Content-type': 'application/json', 'Accept': 'application/json'}
try:
login = session_unity.get(api_login_url, verify=False)
except Exception as oops:
unity_logger.error("Connection Error Occurs: {0}".format(oops))
sys.exit("50")
if login.status_code != 200:
unity_logger.error("Connection Return Code = {0}".format(login.status_code))
sys.exit("60")
elif login.text.find("isPasswordChangeRequired") >= 0: # If i can find string "isPasswordChangeRequired" therefore login is successful
unity_logger.info("Connection established")
return session_unity
else:
unity_logger.error("Login Something went wrong")
sys.exit("70")
def api_logout(api_ip, session_unity): api_logout_url = "https://{0}/api/types/loginSessionInfo/action/logout".format(api_ip) session_unity.headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
try:
logout = session_unity.post(api_logout_url, verify=False)
except Exception as oops:
unity_logger.error("Logout Error Occurs: {0}".format(oops))
sys.exit("150")
if logout.status_code != 200:
unity_logger.error("Logout status = {0}".format(logout.status_code))
sys.exit("160")
elif logout.text.find("Logout successful") >= 0:
unity_logger.info("Logout successful")
else:
unity_logger.error("Logout Something went wrong")
sys.exit("170")
def convert_to_zabbix_json(data): output = json.dumps({"data": data}, indent = None, separators = (',',': ')) return output
def send_data_to_zabbix(zabbix_data, storage_name): sender_command = "/usr/bin/zabbix_sender" config_path = "/etc/zabbix/zabbix_agentd.conf" time_of_create_file = int(time.time()) tempfile = "/tmp/{0}{1}.tmp".format(storage_name, time_of_create_file)
with open(temp_file, "w") as f:
f.write("")
f.write("\n".join(zabbix_data))
send_code = subprocess.call([sender_command, "-vv", "-c", config_path, "-s", storage_name, "-T", "-i", temp_file], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
os.remove(temp_file)
return send_code
def discovering_resources(api_user, api_password, api_ip, api_port, storage_name, list_resources): api_session = api_connect(api_user, api_password, api_ip, api_port)
xer = []
try:
for resource in list_resources:
resource_url = "https://{0}:{1}/api/types/{2}/instances?fields=name".format(api_ip, api_port, resource)
resource_info = api_session.get(resource_url, verify=False)
resource_info = json.loads(resource_info.content.decode('utf8'))
discovered_resource = []
for one_object in resource_info['entries']:
if ['lun', 'pool'].count(resource) == 1:
one_object_list = {}
one_object_list["{#ID}"] = one_object['content']['id']
one_object_list["{#NAME}"] = one_object['content']['name'].replace(' ', '_')
discovered_resource.append(one_object_list)
else:
one_object_list = {}
one_object_list["{#ID}"] = one_object['content']['id']
discovered_resource.append(one_object_list)
converted_resource = convert_to_zabbix_json(discovered_resource)
timestampnow = int(time.time())
xer.append("%s %s %s %s" % (storage_name, resource, timestampnow, converted_resource))
except Exception as oops:
unity_logger.error("Error occurs in discovering")
sys.exit("1000")
api_session_logout = api_logout(api_ip, api_session)
return send_data_to_zabbix(xer, storage_name)
def get_status_resources(api_user, api_password, api_ip, api_port, storage_name, list_resources): api_session = api_connect(api_user, api_password, api_ip, api_port)
state_resources = [] # This list will persist state of resources (pool, lun, fcPort, battery, diks, ...) on zabbix format
try:
for resource in list_resources:
# Create different URI for different resources
if ['pool'].count(resource) == 1:
resource_url = "https://{0}:{1}/api/types/{2}/instances?fields=name,health,sizeTotal,sizeUsed,sizeSubscribed".format(api_ip, api_port, resource)
elif ['lun'].count(resource) == 1:
resource_url = "https://{0}:{1}/api/types/{2}/instances?fields=name,health,sizeTotal,sizeAllocated".format(api_ip, api_port, resource)
else:
resource_url = "https://{0}:{1}/api/types/{2}/instances?fields=name,health,needsReplacement".format(api_ip, api_port, resource)
# Get info about one resource
resource_info = api_session.get(resource_url, verify=False)
resource_info = json.loads(resource_info.content.decode('utf8'))
timestampnow = int(time.time())
if ['ethernetPort', 'fcPort', 'sasPort'].count(resource) == 1:
for one_object in resource_info['entries']:
key_health = "health.{0}.[{1}]".format(resource, one_object['content']['id'].replace(' ', '_'))
key_status = "link.{0}.[{1}]".format(resource, one_object['content']['id'].replace(' ', '_'))
state_resources.append("%s %s %s %s" % (storage_name, key_health, timestampnow, one_object['content']['health']['value']))
# Get state of interfaces from description
descriptionIds = str(one_object['content']['health']['descriptionIds'][0]) # Convert description to string
if descriptionIds.find("LINK_UP") >= 0: # From description i can known, link is up or link is down
link_status = 10
elif descriptionIds.find("LINK_DOWN") >=0:
link_status = 11
state_resources.append("%s %s %s %s" % (storage_name, key_status, timestampnow, link_status))
elif ['lun'].count(resource) == 1:
for one_object in resource_info['entries']:
key_health = "health.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_')) # Use lun name instead lun id on zabbix key
key_sizeTotal = "sizeTotal.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_'))
key_sizeAllocated = "sizeAllocated.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_'))
state_resources.append("%s %s %s %s" % (storage_name, key_health, timestampnow, one_object['content']['health']['value']))
state_resources.append("%s %s %s %s" % (storage_name, key_sizeTotal, timestampnow, one_object['content']['sizeTotal']))
state_resources.append("%s %s %s %s" % (storage_name, key_sizeAllocated, timestampnow, one_object['content']['sizeAllocated']))
elif ['pool'].count(resource) == 1:
for one_object in resource_info['entries']:
key_health = "health.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_')) # Use pull name instead lun id on zabbix key
key_sizeUsedBytes = "sizeUsedBytes.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_'))
key_sizeTotalBytes = "sizeTotalBytes.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_'))
key_sizeSubscribedBytes = "sizeSubscribedBytes.{0}.[{1}]".format(resource, one_object['content']['name'].replace(' ', '_'))
state_resources.append("%s %s %s %s" % (storage_name, key_health, timestampnow, one_object['content']['health']['value']))
state_resources.append("%s %s %s %s" % (storage_name, key_sizeUsedBytes, timestampnow, one_object['content']['sizeUsed']))
state_resources.append("%s %s %s %s" % (storage_name, key_sizeTotalBytes, timestampnow, one_object['content']['sizeTotal']))
state_resources.append("%s %s %s %s" % (storage_name, key_sizeSubscribedBytes, timestampnow, one_object['content']['sizeSubscribed']))
else:
for one_object in resource_info['entries']:
# Get state of resources from description
descriptionIds = str(one_object['content']['health']['descriptionIds'][0]) # Convert description to string
if descriptionIds.find("ALRT_COMPONENT_OK") >= 0:
running_status = 8
elif descriptionIds.find("ALRT_DISK_SLOT_EMPTY") >= 0:
running_status = 6
else:
running_status = 5
key_health = "health.{0}.[{1}]".format(resource, one_object['content']['id'].replace(' ', '_'))
key_status = "running.{0}.[{1}]".format(resource, one_object['content']['id'].replace(' ', '_'))
state_resources.append("%s %s %s %s" % (storage_name, key_health, timestampnow, one_object['content']['health']['value']))
state_resources.append("%s %s %s %s" % (storage_name, key_status, timestampnow, running_status))
except Exception as oops:
unity_logger.error("Error occured in get state")
sys.exit("1000")
api_session_logout = api_logout(api_ip, api_session)
return send_data_to_zabbix(state_resources, storage_name)
def main():
unity_parser = argparse.ArgumentParser()
unity_parser.add_argument('--api_ip', action="store", help="Where to connect", required=True)
unity_parser.add_argument('--api_port', action="store", required=True)
unity_parser.add_argument('--api_user', action="store", required=True)
unity_parser.add_argument('--api_password', action="store", required=True)
unity_parser.add_argument('--storage_name', action="store", required=True)
group = unity_parser.add_mutually_exclusive_group(required=True)
group.add_argument('--discovery', action ='store_true')
group.add_argument('--status', action='store_true')
arguments = unity_parser.parse_args()
list_resources = ['battery','ssd','ethernetPort','fcPort','sasPort','fan','powerSupply','storageProcessor','lun','pool','dae','dpe','ioModule','lcc','memoryModule','ssc','uncommittedPort','disk']
if arguments.discovery:
result_discovery = discovering_resources(arguments.api_user, arguments.api_password, arguments.api_ip, arguments.api_port, arguments.storage_name, list_resources)
print (result_discovery)
elif arguments.status:
result_status = get_status_resources(arguments.api_user, arguments.api_password, arguments.api_ip, arguments.api_port, arguments.storage_name, list_resources)
print (result_status)
if name == "main": main()
Hello, I have been able to evolve a little on my work and I complete the information. I manage to recover data of this type:
2024-07-11 09:26:02,489 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=health.memoryModule.[spb_mm_2], timestamp=1720682760, value=5 2024-07-11 09:26:02,496 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,496 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=running.memoryModule.[spb_mm_2], timestamp=1720682760, value=8 2024-07-11 09:26:02,502 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,502 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=health.memoryModule.[spb_mm_3], timestamp=1720682760, value=5 2024-07-11 09:26:02,508 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,508 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=running.memoryModule.[spb_mm_3], timestamp=1720682760, value=8 2024-07-11 09:26:02,513 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,514 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=health.disk.[dae_1_0_disk_0], timestamp=1720682761, value=5 2024-07-11 09:26:02,519 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,519 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=running.disk.[dae_1_0_disk_0], timestamp=1720682761, value=8 2024-07-11 09:26:02,525 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,525 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=health.disk.[dae_1_0_disk_1], timestamp=1720682761, value=5 2024-07-11 09:26:02,530 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,530 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=running.disk.[dae_1_0_disk_1], timestamp=1720682761, value=8 2024-07-11 09:26:02,536 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,537 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=health.disk.[dae_1_0_disk_2], timestamp=1720682761, value=5 2024-07-11 09:26:02,543 - unity_logger - DEBUG - Zabbix sender return code: 2 2024-07-11 09:26:02,543 - unity_logger - DEBUG - Sending to Zabbix: host=DellEMC_unity_rgi1, key=running.disk.[dae_1_0_disk_2], timestamp=1720682761, value=8
But sending to zabbix I don't have to report data because I have a return code:2
Here is an example of a Discovry Rule
And Item prototype
Can you please help me to report the data value of each element discovered in Zabbix?
Issue Resolved
Hello I have a problem of the same type I have a Zabbix server proxy and a Zabbix main server, the latter monitoring the Zabbix proxy. From the Zabbix proxy I have the Python script that is run to explore my Dell Unity and upload all the discovery elements in my Zabbix but I have a problem to remount the elements in Zabbix HMI.
root@deb:/usr/lib/zabbix/externalscripts# python3 unity_get_state.py --api_ip ... --api_port 443 --api_user ** --api_password * --storage_name DellEMC_unity --discovery 1 root@deb:/usr/lib/zabbix/externalscripts# python3 unity_get_state.py --api_ip ...* --api_port 443 --api_user --api_password ***** --storage_name DellEMC_unity --status 1 root@deb:/usr/lib/zabbix/externalscripts#
in the log unity_state.log I don't have an error
2024-07-09 11:41:07,751 - unity_logger - INFO - Connection established 2024-07-09 11:41:12,247 - unity_logger - INFO - Logout successful 2024-07-09 11:41:35,916 - unity_logger - INFO - Connection established 2024-07-09 11:41:40,324 - unity_logger - INFO - Logout successful 2024-07-09 11:41:50,849 - unity_logger - INFO - Connection established 2024-07-09 11:41:55,705 - unity_logger - INFO - Logout successful
on the other hand when I do the tests manually
root@deb:/usr/bin# zabbix_sender -z server_zabbix -p 10051 -s "DellEMC_unity" -k "health.disk.[{#ID}] " -o 4 -vv zabbix_sender [4022880]: DEBUG: In connect_to_server() [server_zabbix]:10051 [timeout:60, connection timeout:3] zabbix_sender [4022880]: DEBUG: In is_ip4() ip:'...**' zabbix_sender [4022880]: DEBUG: End of is_ip4():SUCCEED zabbix_sender [4022880]: DEBUG: answer [{"response":"success","info":"processed: 0; failed: 1; total: 1; seconds spent: 0.000019"}] Response from "server_zabbix:10051": "processed: 0; failed: 1; total: 1; seconds spent: 0.000019" sent: 1; skipped: 0; total: 1 root@deb:/usr/bin#
Can you help me figure out what's wrong?