def main(): # take some input parser = argparse.ArgumentParser(description="collect metrics from VNX and import into InfluxDB. Assumes naviseccli is in the PATH") parser.add_argument('--vnx', required=True, action='append', help="VNX SP to connect to") parser.add_argument('--vnx-username', default="admin", help="navisec username") parser.add_argument('--vnx-password', default="changeme", help="navisec password") parser.add_argument('--influx-dsn', default=influx_dsn_default, help="InfluxDB DSN, eg. %s" % influx_dsn_default) parser.add_argument('--debug', '-d', action='store_true', help="enable debugging") args = parser.parse_args() # loop over vCenters and collect metrics for vnx in args.vnx: meas = "vnxprop.%s" % (convert_to_alnum(vnx)) results = build_vnx(vnx, vnx_tags, vnx_fields, measurement=meas, args=args) if args.debug: print "Results of VNX query:" for ts in results: print "Measurement:", ts.measurement print "Tags:", ts.tags print "Fields:", ts.fields print else: write_results(args.influx_dsn, results)
def agg_by_vcenter(results): # agg_toplevelfolder is dictionary whose values are # InfluxResults # agg_vcenter['vcenter'] agg_vcenter = {} meas_base = "vmagg_vcenter" for ts in results: vcenter = convert_to_alnum(ts.tags['vcenter']) # new vcenter, which means new aggregrate if vcenter not in agg_vcenter: agg_obj = InfluxResult08("%s.%s" % (meas_base, vcenter)) for tag in ['vcenter']: agg_obj.tags[tag] = ts.tags[tag] for field in ts.fields: agg_obj.fields[field] = ts.fields[field] agg_obj.timestamp = ts.timestamp agg_vcenter[vcenter] = agg_obj else: agg_obj = agg_vcenter[vcenter] # aggregate on fields for field in ts.fields: if field not in agg_obj.fields: agg_obj.fields[field] = ts.fields[field] elif type(agg_obj.fields[field]) in (int, long, float): agg_obj.fields[field] += ts.fields[field] # now flatten to a list ret = [] for vcenter in agg_vcenter: ret.append(agg_vcenter[vcenter]) return ret
def build_vmresultset(service_instance, tags, fields, measurement='vmprop'): """Build a list of InfluxResult objects Arguments: service_instance: a service instance as returned from pyvim.connect.smartconnect tags: a list of VM properties to use as Influx tags fields: a list of VM propertries to use as Influx fields measurement: the influx db measurement name to use Results: A list of InfluxResult objects suitable to insert into a database. """ res = [] root_folders = service_instance.content.rootFolder.childEntity for child in root_folders: if hasattr(child, 'vmFolder'): datacenter = child else: continue meas = "%s.%s" % (measurement, convert_to_alnum(datacenter.name)) dc_children = get_vms(service_instance, datacenter.vmFolder, "", tags, fields, meas) for dc_child in dc_children: dc_child.tags['datacenter'] = datacenter.name res.extend(dc_children) return res
def main(): # take some input parser = argparse.ArgumentParser(description="collect metrics from XtremIO and import into InfluxDB") parser.add_argument('--xms', required=True, action='append', help="XtremIO XMS to connect to") parser.add_argument('--xmsadmin-username', default="xmsadmin", help="xmsadmin username") parser.add_argument('--xmsadmin-password', default="changeme", help="xmsadmin password") parser.add_argument('--xms-username', default="admin", help="xms user username") parser.add_argument('--xms-password', default="changeme", help="xms user password") parser.add_argument('--influx-dsn', default=influx_dsn_default, help="InfluxDB DSN, eg. %s" % influx_dsn_default) parser.add_argument('--debug', '-d', action='store_true', help="enable debugging") args = parser.parse_args() # loop over vCenters and collect metrics for xms in args.xms: meas = "xioprop.%s" % (convert_to_alnum(xms)) results = build_xiocluster(xms, xio_tags, xio_fields, measurement=meas, args=args) if args.debug: print "Results of XMS query:" for ts in results: print "Measurement:", ts.measurement print "Tags:", ts.tags print "Fields:", ts.fields print else: write_results(args.influx_dsn, results)
def build_vnx(vnx, tags, fields, measurement='vnxprop', args=None): """Build a list of InfluxResult objects Arguments: vnx: the hostname of a VNX SP to connect to tags: a list of VNX properties to use as Influx tags fields: a list of VNX propertries to use as Influx fields measurement: the influx db measurement name to use args: a argparse Namespace with the vnx_{username,password} fields Results: A list of InfluxResult objects suitable to insert into a database. """ res = [] # run the naviseccli command # assumes that it is in the PATH cmd = ["naviseccli", "-User", args.vnx_username, "-Password", args.vnx_password, "-Scope", "0", "-h", vnx, "storagepool", "-list", "-capacities", "-luns"] naviout = check_output(cmd) # build the result data structures recs = [] data = {} for line in naviout.splitlines(): # skip whitespace and blank lines if line == "" or line.isspace(): continue # colon-delimited key value pairs key, value = line.split(":", 2) key = convert_to_alnum(key.strip()) value = value.strip() # Pool Name signals the start of a new record, so push the current # record onto the list if we parsed anything from it if key == "Pool_Name" and len(data.keys()) > 0: recs.append(data) data = {} if key == "LUNs": # LUNs are logically a list value = value.split(",") # synthesize a LUN_Count field data["LUN_Count"] = len(value) # try to convert to numbers elif value.isdigit(): value = int(value) elif re.match(r'[0-9]+\.[0-9]*', value): value = float(value) elif value.endswith(hr.SYMBOLS): value = hr.human2bytes(value) else: value = convert_to_alnum(value.strip()) data[key] = value # grab the final record if len(data.keys()) > 0: recs.append(data) for data in recs: missing_data = False meas = "%s.%s" % (measurement, convert_to_alnum(data['Pool_Name'])) ts = InfluxResult08(meas) for tag in tags: try: ts.tags[tag] = data[tag] except KeyError as e: print "Could not process %s for data %s" % (tag, data['name']) missing_data = True for field in fields: try: ts.fields[field] = data[field] except KeyError as e: print "Could not process %s for data %s" % (field, data['name']) missing_data = True ts.tags['vnx'] = vnx if not missing_data: res.append(ts) return res
def main(): # take some input parser = argparse.ArgumentParser(description="collect metrics from vSphere and import into InfluxDB") parser.add_argument('--vcenter', required=True, action='append', help="vCenter to connect to") parser.add_argument('--vs-username', default="admin", help="vSphere username") parser.add_argument('--vs-password', default="changeme", help="vSphere password") parser.add_argument('--vs-port', type=int, default=443, help="vSphere port") parser.add_argument('--influx-dsn', default=influx_dsn_default, help="InfluxDB DSN, eg. %s" % influx_dsn_default) parser.add_argument('--debug', '-d', action='store_true', help="enable debugging") args = parser.parse_args() silence_warnings() # loop over vCenters and collect metrics for vcenter in args.vcenter: service_instance = None try: service_instance = connect.SmartConnect(host=vcenter, user=args.vs_username, pwd=args.vs_password, port=args.vs_port) atexit.register(connect.Disconnect, service_instance) except Exception as e: print "Unable to connect to %s" % vcenter continue meas = "vmprop.%s" % (convert_to_alnum(vcenter)) results = build_vmresultset(service_instance, vm_tags, vm_fields, measurement=meas) for ts in results: ts.tags['vcenter'] = vcenter if len(ts.tags['folderPath'].split('/')) >= 2: ts.tags['topLevelFolder'] = ts.tags['folderPath'].split('/')[1] else: ts.tags['topLevelFolder'] = "None" # collect the results and some aggregates output = [] output.extend(results) output.extend(agg_by_topLevelFolder(results)) output.extend(agg_by_vcenter(results)) # now write the output to the database if args.debug: print "Results of vSphere query:" for ts in output: print "Measurement:", ts.measurement print "Tags:", ts.tags print "Fields:", ts.fields print else: write_results(args.influx_dsn, output)
def get_vms(service_instance, folder, parent_path, tags, fields, measurement): """Returns a list of InfluxResult objects representing the child objects of vm_or_folder Arguments: service_instance: a service instance as returned from pyVim.connect.SmartConnect vm_or_folder: the root of the VM/folder tree to search parent_path: the path of parent of vm_or_folder tags: a list of VM properties to use as Influx tags fields: a list of VM propertries to use as Influx fields measurement: the influx db measurement name to use Results: A list of InfluxResult objects suitable to insert into a database. """ res = [] # collect child folders #print parent_path folder_spec = pchelper.get_container_view(service_instance, obj_type=[vim.Folder], container=folder, recursive=False) folders = pchelper.collect_properties(service_instance, view_ref=folder_spec, obj_type=vim.Folder, path_set=['name'], include_mors=True) for child_folder in folders: meas = "%s.%s" % (measurement, convert_to_alnum(child_folder['obj'].name)) child_vms = get_vms(service_instance, child_folder['obj'], "%s/%s" % (parent_path, child_folder['obj'].name), tags, fields, meas) res.extend(child_vms) # collect child vms props = [] props.extend(tags) props.extend(fields) vm_spec = pchelper.get_container_view(service_instance, obj_type=[vim.VirtualMachine], container=folder, recursive=False) vms = pchelper.collect_properties(service_instance, view_ref=vm_spec, obj_type=vim.VirtualMachine, path_set=props, include_mors=False) # put each child into res for vm in vms: missing_data = False meas = "%s.%s" % (measurement, convert_to_alnum(vm['name'])) ts = InfluxResult08(meas) for tag in tags: try: ts.tags[tag] = vm[tag] except KeyError as e: print "Could not process %s for vm %s" % (tag, vm['name']) missing_data = True for field in fields: try: ts.fields[field] = vm[field] except KeyError as e: print "Could not process %s for vm %s" % (field, vm['name']) missing_data = True ts.tags['folderPath'] = parent_path if not missing_data: res.append(ts) return res