存储系统的稳定运行对企业数据中心至关重要。为了确保 EMC Unity 300 存储系统的高可用性和性能,管理员需要一个高效的监控解决方案。本文将介绍如何使用 Python 编写一个脚本,通过 API 接口监控 EMC Unity 300 存储系统的多个关键指标,包括系统信息、存储池信息、逻辑单元信息和物理硬盘信息。
一、准备工作
安装必要的 Python 库
确保已安装 requests 库,用于发送 HTTP 请求。
安装命令:pip install requests
获取存储系统访问权限
确保具有 EMC Unity 300 存储系统的管理员访问权限。
准备好存储系统的 IP 地址、用户名和密码。
二、Python 脚本详细介绍
以下是完整的 Python 脚本,用于监控 EMC Unity 300 存储系统。
#!/usr/bin/env python
# -*- coding : utf-8 -*-
# @Time : 2024/5/8 15:58
# @Author : 我是Rain呀 -- (。♥ᴗ♥。)
# @File : EMC_UNITY300_DEMO.py
# @Software : PyCharm
import requests
import urllib3
import json
import argparse
import getpass
class UserInput:
# 创建参数解析器
parser = argparse.ArgumentParser(description="User Input Parser")
parser.add_argument('--ipaddress', type=str, help='ipaddress', required=True)
parser.add_argument('--username', type=str, help='Username', default='admin')
parser.add_argument('--password', type=str, help='Password', default=None)
parser.add_argument('--mode', type=str, help='models', required=True)
# 解析用户输入的参数
args = parser.parse_args()
class EmcUnity300(UserInput):
# 常量
BASE_URL = 'https://{}/api'.format(UserInput.args.ipaddress.strip()) # 存储系统的基础 URL
if UserInput.args.password is None:
UserInput.args.password = getpass.getpass("Enter your password: ")
AUTH = (UserInput.args.username, UserInput.args.password) # 认证信息 (用户名, 密码)
HEADERS = {
"Accept": "application/json; version=1.0",
"Accept-Language": "en-US",
"Content-Type": "application/json",
"X-EMC-REST-CLIENT": "true",
"Application-Type": "your_plugin_name/your_plugin_version"
} # 请求头
def __init__(self):
urllib3.disable_warnings()
self.session = requests.Session()
self.session.verify = False
def send_request(self, endpoint, params=None):
url = f"{self.BASE_URL}/{endpoint}"
headers = self.HEADERS.copy()
# 如果会话尚未进行身份验证,则使用默认身份验证信息
if self.session.auth is None:
self.session.auth = self.AUTH
# 如果存在 CSRF 令牌,则添加到请求头中
if self.session.auth and not self.session.auth[1]:
del headers['EMC-CSRF-TOKEN']
try:
# 发送 HTTP 请求
with self.session.get(url, headers=headers, params=params) as response:
# 检查响应状态
response.raise_for_status()
# 解析 JSON 响应
return response.json()
except requests.RequestException as e:
# 处理 HTTP 请求异常
print("HTTP请求发生错误:", e)
return None
except json.JSONDecodeError as e:
# 处理 JSON 解析异常
print("JSON解析错误:", e)
return None
def get_system(self):
# 获取物理系统信息
endpoint = 'instances/system/0'
params = {'fields': 'name,health,model,serialNumber,currentPower,avgPower'}
result = self.send_request(endpoint, params=params)
if result:
# 构造系统信息的 JSON 字符串
return json.dumps({
"system_name": result.get("content", {}).get("name"),
"system_model": result.get("content", {}).get("model"),
"system_serialNumber": result.get("content", {}).get("serialNumber"),
"system_currentPower": result.get("content", {}).get("currentPower"),
"system_avgPower": result.get("content", {}).get("avgPower"),
"system_health": result.get("content", {}).get("health", {}).get("value")
})
return None
def get_pool(self):
# 获取存储池信息
endpoint = 'types/pool/instances'
params = {
'fields': 'health,name,sizeTotal,sizeFree,percentUsed::sizeTotal eq 0 ? 0.0 : ((sizeUsed / sizeTotal) * '
'100),snapSizeUsed,sizeUsed,type'}
result = self.send_request(endpoint, params=params)
if result:
# 构造存储池信息的 JSON 字符串
return json.dumps([{
"name": data.get("content", {}).get("name"),
"sizeFree": data.get("content", {}).get("sizeFree"),
"sizeTotal": data.get("content", {}).get("sizeTotal"),
"sizeUsed": data.get("content", {}).get("sizeUsed"),
"percentUsed": data.get("content", {}).get("percentUsed"),
"health": data.get("content", {}).get("health", {}).get("value")
} for data in result.get("entries", [])])
return None
def get_lun(self):
# 获取逻辑单元信息
endpoint = 'types/lun/instances'
params = {'filter': '(type eq 2)',
'fields': 'health,name,sizeTotal,percentAllocated::sizeTotal eq 0 ? 0.0 : ((sizeAllocated / '
'sizeTotal) * 100),sizeAllocated,wwn,sizeUsed'}
result = self.send_request(endpoint, params=params)
if result:
# 构造逻辑单元信息的 JSON 字符串
return json.dumps([{
"name": data.get("content", {}).get("name"),
"sizeTotal": data.get("content", {}).get("sizeTotal"),
"sizeAllocated": data.get("content", {}).get("sizeAllocated"),
"wwn": data.get("content", {}).get("wwn"),
"percentAllocated": data.get("content", {}).get("percentAllocated"),
"health": data.get("content", {}).get("health", {}).get("value")
} for data in result.get("entries", [])])
return None
def get_disk(self):
# 获取物理硬盘信息
endpoint = 'types/disk/instances'
params = {'fields': 'health,name,diskTechnology,tierType,size,rpm'}
result = self.send_request(endpoint, params=params)
if result:
# 构造物理硬盘信息的 JSON 字符串
return json.dumps([{
"name": data.get("content", {}).get("name"),
"size": data.get("content", {}).get("size"),
"rpm": data.get("content", {}).get("rpm"),
"health": data.get("content", {}).get("health", {}).get("value")
} for data in result.get("entries", [])])
return None
def execute_function(self):
func = getattr(self, UserInput.args.mode.strip(), None)
print(func()) if func else print("Invalid function name. Please try again.")
if __name__ == '__main__':
EmcUnity300().execute_function()
三、脚本使用说明
参数说明
--ipaddress:存储系统的 IP 地址,必需参数。
--username:用户名,默认值为 admin。
--password:密码,默认值为空。如果未提供,则在运行时提示输入。
--mode:操作模式,必需参数。可以是 get_system、get_pool、get_lun 或 get_disk。
运行示例
获取系统信息:python HP_DL380_DEMO.py --ipaddress 192.168.1.100 --username admin --password mypassword --mode get_system
获取存储池信息:python HP_DL380_DEMO.py --ipaddress 192.168.1.100 --username admin --password mypassword --mode get_pool
获取逻辑单元信息:python HP_DL380_DEMO.py --ipaddress 192.168.1.100 --username admin --password mypassword --mode get_lun
获取物理硬盘信息:python HP_DL380_DEMO.py --ipaddress 192.168.1.100 --username admin --password mypassword --mode get_disk
四、脚本功能解析
UserInput 类
解析用户输入的参数,并将其作为全局变量
如果您在开发 Python/Shell 脚本或 Zabbix 模板过程中遇到问题,或者有开发模板或脚本的需求,欢迎随时添加 QQ:1030202304,与我一起沟通交流。
错误信息