check_vcenter_multipath
This commit is contained in:
parent
ed17eca658
commit
3945f50999
176
check_vcenter_multipath
Executable file
176
check_vcenter_multipath
Executable file
@ -0,0 +1,176 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from pyVmomi import vim
|
||||||
|
import pyVim.connect
|
||||||
|
import sys
|
||||||
|
import atexit
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import siteconf
|
||||||
|
|
||||||
|
class Main:
|
||||||
|
def __init__(self):
|
||||||
|
self.ok = []
|
||||||
|
self.warning = []
|
||||||
|
self.critical = []
|
||||||
|
self.site_conf = siteconf.read()
|
||||||
|
self.get_args()
|
||||||
|
|
||||||
|
def get_args(self):
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='check multipath redundancy')
|
||||||
|
|
||||||
|
parser.add_argument('-s', '--site',
|
||||||
|
required=True,
|
||||||
|
action='store',
|
||||||
|
help='name of the site to connect to')
|
||||||
|
|
||||||
|
parser.add_argument('-H', '--host',
|
||||||
|
required=True,
|
||||||
|
action='store',
|
||||||
|
help='host to check')
|
||||||
|
|
||||||
|
self.args = parser.parse_args()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.connect()
|
||||||
|
host = self.get_obj([vim.HostSystem], self.args.host)
|
||||||
|
if not host:
|
||||||
|
print("host not found")
|
||||||
|
exit(1)
|
||||||
|
self.pathcheck(host)
|
||||||
|
self.status_exit()
|
||||||
|
|
||||||
|
def map_uuid_to_datastore(self, host):
|
||||||
|
canonical_datastore = {}
|
||||||
|
for ds in host.datastore:
|
||||||
|
try:
|
||||||
|
vmfs = ds.info.vmfs
|
||||||
|
except:
|
||||||
|
continue # not vmfs
|
||||||
|
for ext in vmfs.extent:
|
||||||
|
canonical_datastore[ext.diskName] = {
|
||||||
|
'name': vmfs.name,
|
||||||
|
'local': vmfs.local
|
||||||
|
}
|
||||||
|
|
||||||
|
self.uuid_datastore = {}
|
||||||
|
for lun in host.config.storageDevice.scsiLun:
|
||||||
|
ds = canonical_datastore.get(lun.canonicalName)
|
||||||
|
if not ds:
|
||||||
|
continue # not a datastore
|
||||||
|
#print(f"uuid {lun.uuid} name {ds['name']} local {ds['local']}")
|
||||||
|
self.uuid_datastore[lun.uuid] = ds
|
||||||
|
|
||||||
|
def pathcheck(self, host):
|
||||||
|
self.map_uuid_to_datastore(host)
|
||||||
|
storage_system = host.configManager.storageSystem
|
||||||
|
multipath_info = storage_system.storageDeviceInfo.multipathInfo
|
||||||
|
if multipath_info is None:
|
||||||
|
self.critical.append("no multipath info")
|
||||||
|
return
|
||||||
|
for lun in multipath_info.lun:
|
||||||
|
ds = self.uuid_datastore.get(lun.id)
|
||||||
|
if not ds:
|
||||||
|
#print(f"lun {lun.id} is not a datastore")
|
||||||
|
continue # not a datastore
|
||||||
|
|
||||||
|
active, standby, dead, other = [], [], [], []
|
||||||
|
for path in lun.path:
|
||||||
|
#print(f"{path.name} {path.pathState} {path.adapter} {path.transport.__class__.__name__ if path.transport else '?'}")
|
||||||
|
if path.pathState == 'active':
|
||||||
|
active.append(path)
|
||||||
|
elif path.pathState == 'standby':
|
||||||
|
standby.append(path)
|
||||||
|
elif path.pathState == 'dead':
|
||||||
|
dead.append(path)
|
||||||
|
else:
|
||||||
|
other.append(path)
|
||||||
|
|
||||||
|
if ds['local']:
|
||||||
|
minpath = 1
|
||||||
|
prefix = f"{ds['name']} (local)"
|
||||||
|
elif re.search(r'-local\d?$', ds['name']):
|
||||||
|
minpath = 1
|
||||||
|
prefix = f"{ds['name']} (local-by-name)"
|
||||||
|
else:
|
||||||
|
minpath = 2
|
||||||
|
prefix = f"{ds['name']}"
|
||||||
|
paths = f"{len(active)}+{len(standby)} active/standby"
|
||||||
|
if len(dead) > 0:
|
||||||
|
paths += f", {len(dead)}"
|
||||||
|
if len(other) > 0:
|
||||||
|
for path in other:
|
||||||
|
paths += f", 1 {path.pathState}"
|
||||||
|
paths += " paths"
|
||||||
|
if len(active) + len(standby) < minpath:
|
||||||
|
self.critical.append(f"{prefix} NOT REDUNDANT: {paths}")
|
||||||
|
elif len(dead) > 0:
|
||||||
|
self.critical.append(f"{prefix} DEAD PATH: {paths}")
|
||||||
|
elif len(other) > 0:
|
||||||
|
self.warning.append(f"{prefix} OTHER STATE: {paths}")
|
||||||
|
else:
|
||||||
|
self.ok.append(f"{prefix}: {paths}")
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
if not self.args.site in self.site_conf:
|
||||||
|
print(f"site not found: {self.args.site}")
|
||||||
|
exit(1)
|
||||||
|
host = self.site_conf[self.args.site]['vcenter']
|
||||||
|
user = self.site_conf[self.args.site]['vcenter_user']
|
||||||
|
passwd = self.site_conf[self.args.site]['vcenter_passwd']
|
||||||
|
|
||||||
|
si = pyVim.connect.SmartConnect(
|
||||||
|
host = host,
|
||||||
|
user = user,
|
||||||
|
pwd = passwd,
|
||||||
|
disableSslCertValidation = True
|
||||||
|
)
|
||||||
|
atexit.register(pyVim.connect.Disconnect, si)
|
||||||
|
self.content = si.RetrieveContent()
|
||||||
|
|
||||||
|
def get_obj(self, vimtype, name):
|
||||||
|
"""
|
||||||
|
Return an object by name, if name is None the
|
||||||
|
first found object is returned
|
||||||
|
"""
|
||||||
|
obj = None
|
||||||
|
container = self.content.viewManager.CreateContainerView(
|
||||||
|
self.content.rootFolder, vimtype, True)
|
||||||
|
for c in container.view:
|
||||||
|
if name:
|
||||||
|
if c.name == name:
|
||||||
|
obj = c
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
obj = c
|
||||||
|
break
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def status_exit(self):
|
||||||
|
message = []
|
||||||
|
exitcode = 0
|
||||||
|
if len(self.critical) > 0:
|
||||||
|
exitcode = 2
|
||||||
|
message.append("CRITICAL: "+ " / ".join(self.critical))
|
||||||
|
if len(self.warning) > 0:
|
||||||
|
if exitcode == 0:
|
||||||
|
exitcode = 1
|
||||||
|
message.append("WARNING: "+ " / ".join(self.warning))
|
||||||
|
if exitcode > 0:
|
||||||
|
print(" / ".join(message))
|
||||||
|
sys.exit(exitcode)
|
||||||
|
|
||||||
|
print("OK: "+ " / ".join(self.ok))
|
||||||
|
sys.exit(exitcode)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
Main().run()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"UNKNOWN: {e}")
|
||||||
|
print(type(e))
|
||||||
|
sys.exit(3)
|
||||||
|
|
||||||
|
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||||
Loading…
x
Reference in New Issue
Block a user