import requests
import pprint
import datetime
import time
import json
import sys
import logging
import argparse
UNISPHERE_SERVER = ''
UNISPHERE_USER = ''
UNISPHERE_PASS = ''
UNISPHERE_REST_URL = 'https://' + UNISPHERE_SERVER + ':8443/univmax/restapi'
VERSION = '1.0'
def parse_parameters():
sid_parser = argparse.ArgumentParser(add_help=False)
sid_parser.add_argument('--sid', help='Symmetrix ID', required=True)
epilog = '''
Example of use:
%s list
%s srp --sid xxxx
%s performance --sid xxxx --hours 2
%s -v performance
%s performance -h
''' % (sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0])
parser = argparse.ArgumentParser(description='Sample Script to collect \
information from Unisphere for VMAX REST API',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=epilog)
parser.add_argument('--version',
action='version',
version=VERSION)
parser.add_argument('--verbose', '-v',
action='store_true',
help='verbose flag',
dest='verbose')
subparsers = parser.add_subparsers(title='Commands')
list_parser = subparsers.add_parser('list',
help='List VMAXs arrays managed by Unisphere')
list_parser.set_defaults(func=list_vmax)
list_parser = subparsers.add_parser('listsg',
help='List VMAX storage groups',
parents=[sid_parser])
list_parser.set_defaults(func=list_sg)
srp_parser = subparsers.add_parser('srp',
help='List SRP information',
parents=[sid_parser])
srp_parser.set_defaults(func=list_srp)
performance_parser = subparsers.add_parser('performance',
help='List VMAX Array performance',
parents=[sid_parser])
performance_parser.add_argument('--min',
type=int,
help='Minutes ago to gather performance information',
dest='min')
performance_parser.add_argument('--hours',
type=int,
help='Hours ago to gather performance information',
dest='hours')
performance_parser.add_argument('--days',
type=int,
help='Days ago to gather performance information',
dest='days')
performance_parser.set_defaults(func=array_performance)
if len(sys.argv) < 2:
parser.print_help()
sys.exit(0)
return parser.parse_args()
def setup_logging():
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(funcName)s - %(levelname)s - %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p')
logging.getLogger("requests").setLevel(logging.WARNING)
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
return logging.getLogger(__name__)
def msg(color, msg, exitcode=0):
if color == 'blue' : color = '\033[1;34m'
elif color == 'red' : color = '\033[1;31m'
elif color == 'green' : color = '\033[0;32m'
elif color == 'yellow' : color = '\033[0;33m'
elif color == 'p_color' : color = '\033[01;37;44m'
elif color == 'nocolor' : color = '0'
else:
print("Error: msg function: invalid color:" , color)
sys.exit(1)
resetcolor ='\033[0m'
print(color + msg + resetcolor)
if exitcode:
sys.exit(exitcode)
def epoch_time_ms_now():
return int(time.time() * 1000)
def epoch_time_min_ago(minutes=5):
return int(epoch_time_ms_now() - (60 * minutes * 1000))
def epoch_time_hours_ago(hours=1):
return int(epoch_time_ms_now() - (hours * 3600 * 1000))
def epoch_time_days_ago(days=1):
return int(epoch_time_ms_now() - (days * 24 * 3600 * 1000))
def epoch_time_to_human(timestamp):
return datetime.datetime.fromtimestamp(timestamp/1000).strftime('%c')
def vmax_rest_post(rest_path, request_obj):
log.debug("rest_path: " + rest_path)
if not log.disabled:
log.debug("request_obj:")
pprint.pprint(request_obj)
rest_url = UNISPHERE_REST_URL + rest_path
log.debug(rest_url)
header = { 'content-type' : 'application/json',
'accept' : 'application/json' }
try:
response = requests.post(rest_url,
data=json.dumps(request_obj),
auth=(UNISPHERE_USER, UNISPHERE_PASS),
headers=header,
verify=False)
except Exception as e:
msg("red", str(e))
msg("red", "Error to connect to Unisphere Rest API", 1)
log.debug("Response code %s", response.status_code)
if response.status_code != 200:
pprint.pprint(response.text)
msg("red", "Error to perform POST operation on unisphere. " +
"\nrest_path: " + rest_path +
"\nRest API status_code: " + str(response.status_code) +
"\nError text: " + str(response.text), 1)
if not log.disabled:
log.debug("Rest API response:")
pprint.pprint(json.loads(response.text))
return json.loads(response.text)
def vmax_restapi_get(rest_path):
log.debug("rest_path: " + rest_path)
rest_url = UNISPHERE_REST_URL + rest_path
headers = { 'content-type' : 'application/json',
'accept' : 'application/json' }
try:
response = requests.get(rest_url,
auth=(UNISPHERE_USER, UNISPHERE_PASS),
headers=headers,
verify=False)
except Exception as e:
msg("red", str(e))
msg("red", "Error to connect to Unisphere Rest API", 1)
if response.status_code != 200:
msg("red", "Error to perform GET operation on unisphere." +
"\nrest_path: " + rest_path +
"\nRest API status_code: " + str(response.status_code) +
"\nError text: " + str(response.text), 1)
if not log.disabled:
log.debug("Rest API response:")
pprint.pprint(json.loads(response.text))
return json.loads(response.text)
def list_vmax_details(sid):
log.debug("Getting VMAX details for SID: " + sid)
rest_path = "/system/symmetrix/" + sid
response = vmax_restapi_get(rest_path)
output = "Local: " + str(response['symmetrix'][0]['local'])
output += " Model: " + str(response['symmetrix'][0]['model'])
output += " symmetrixId: " + str(response['symmetrix'][0]['symmetrixId'])
output += " ucode: " + str(response['symmetrix'][0]['ucode'])
msg("blue", output)
def list_vmax(args):
log.debug("Getting list of VMAXs")
rest_path = "/system/symmetrix"
response = vmax_restapi_get(rest_path)
log.debug("Start getting VMAXs details")
for sid in response['symmetrixId']:
list_vmax_details(sid)
def list_sg(args):
log.debug("Getting the list storage groups on VMAX: %s", args.sid)
rest_path = "/sloprovisioning/symmetrix/" + args.sid + "/storagegroup"
response = vmax_restapi_get(rest_path)
for sg in response['storageGroupId']:
print(sg)
def list_srp_details(rest_path):
log.debug("Getting SRP detail: " + rest_path)
response = vmax_restapi_get(rest_path)
srp = response['srp'][0]['srpId']
usable = response['srp'][0]['total_usable_cap_gb'] / 1024
allocated = response['srp'][0]['total_allocated_cap_gb'] / 1024
subscribed = response['srp'][0]['total_subscribed_cap_gb'] / 1024
snapshot = response['srp'][0]['total_snapshot_allocated_cap_gb'] / 1024
free = usable - allocated
print("")
print("SRP: " + srp)
print("Usable TB: " + str(round(usable, 1)))
print("Allocated TB: " + str(round(allocated, 1)))
print("Snapshot TB: " + str(round(snapshot, 1)))
print("Free TB: " + str(round(free, 1)))
print("Subscribed TB: " + str(round(subscribed, 1)))
print("")
def list_srp(args):
log.debug("Getting list of SRPs")
rest_path = "/sloprovisioning/symmetrix/" + str(args.sid) + "/srp"
response = vmax_restapi_get(rest_path)
log.debug("Start getting SRPs details")
for srp in response['srpId']:
list_srp_details(rest_path + "/" + srp)
def get_timestamp(args):
if args.min:
if args.min < 4:
msg("red", "Error: minutes must be greater than 5", 1)
start_time = epoch_time_min_ago(args.min)
elif args.hours:
if args.hours < 1:
msg("red", "Error: hours must be greater than 1", 1)
start_time = epoch_time_hours_ago(args.hours)
elif args.days:
if args.days < 1:
msg("red", "Error: days must be greater than 1", 1)
start_time = epoch_time_days_ago(args.days)
else:
start_time = epoch_time_min_ago(5)
log.debug("start_time:")
log.debug(time.strftime("%d %b %Y %H:%M:%S +0000", \
time.localtime(start_time // 1000)))
return(start_time)
def generate_array_performance_payload(sid, start_time):
log.debug('Symmetrix ID: ' + str(sid))
return {'symmetrixId': str(sid),
"endDate": epoch_time_ms_now(),
"startDate": start_time,
"metrics": ["HostIOs",
"PercentReads",
"PercentWrites",
"PercentHit",
"HostMBs",
"ReadResponseTime",
"WriteResponseTime"],
"dataFormat": "Average" }
def array_performance(args):
log.debug("vmax sid: " + args.sid)
start_time = get_timestamp(args)
rest_path = "/performance/Array/metrics"
request_obj = generate_array_performance_payload(args.sid, start_time)
log.debug("start_time: " + epoch_time_to_human(start_time))
log.debug("end_time : " + epoch_time_to_human(request_obj['endDate']))
response = vmax_rest_post(rest_path, request_obj)
for metrics in response["resultList"]["result"]:
data = epoch_time_to_human(metrics["timestamp"]) + " "
for key, value in metrics.items():
data += key+"="+str(value)+","
data = data[:-1]
msg("blue", data)
def main():
global log
global args
log = setup_logging()
args = parse_parameters()
if not args.verbose:
log.disabled = True
log.debug('CMD line args: %s', vars(args))
args.func(args)
if __name__ == '__main__':
main()