├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE.txt ├── Preview.gif ├── README.md └── root ├── config └── configSample.yaml └── root ├── easy_influx.py ├── esx_snmp.py ├── handlers.py ├── host_classes.py ├── misc_ipmi.py ├── synology_snmp.py └── ups_snmp.py /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gitignore 3 | .github 4 | .gitattributes 5 | *.gif 6 | README.md 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Config 2 | config.yaml 3 | 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | # Windows shortcuts 21 | *.lnk 22 | 23 | # ========================= 24 | # Operating System Files 25 | # ========================= 26 | 27 | # OSX 28 | # ========================= 29 | 30 | .DS_Store 31 | .AppleDouble 32 | .LSOverride 33 | 34 | # Thumbnails 35 | ._* 36 | 37 | # Files that might appear on external disk 38 | .Spotlight-V100 39 | .Trashes 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | 48 | # ========================= 49 | # Development Specific Files 50 | # ========================= 51 | 52 | 53 | # Byte-compiled / optimized / DLL files 54 | __pycache__/ 55 | *.py[cod] 56 | 57 | # C extensions 58 | *.so 59 | 60 | # Distribution / packaging 61 | bin/ 62 | build/ 63 | develop-eggs/ 64 | dist/ 65 | eggs/ 66 | lib/ 67 | lib64/ 68 | parts/ 69 | sdist/ 70 | var/ 71 | *.egg-info/ 72 | .installed.cfg 73 | *.egg 74 | 75 | # Installer logs 76 | pip-log.txt 77 | pip-delete-this-directory.txt 78 | 79 | # Unit test / coverage reports 80 | .tox/ 81 | .coverage 82 | .cache 83 | nosetests.xml 84 | coverage.xml 85 | 86 | # Translations 87 | *.mo 88 | 89 | # Mr Developer 90 | .mr.developer.cfg 91 | .project 92 | .pydevproject 93 | 94 | # Rope 95 | .ropeproject 96 | 97 | # Django stuff: 98 | *.log 99 | *.pot 100 | 101 | # Sphinx documentation 102 | docs/_build/ 103 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | MAINTAINER Ben Dews, bendews 3 | 4 | RUN apt-get update && \ 5 | apt-get install -qy --no-install-recommends ipmitool && \ 6 | apt-get install -qy --no-install-recommends snmp && \ 7 | apt-get install -qy --no-install-recommends python3 && \ 8 | apt-get install -qy --no-install-recommends python3-pip && \ 9 | apt-get install -qy --no-install-recommends python3-setuptools && \ 10 | pip3 install wheel==0.29.0 && \ 11 | pip3 install PyYAML==3.12 && \ 12 | pip3 install requests==2.12.4 && \ 13 | 14 | # cleanup 15 | apt-get clean && \ 16 | rm -rf /tmp/* && \ 17 | rm -rf /var/lib/apt/lists/* && \ 18 | rm -rf /var/tmp 19 | 20 | # add local files 21 | COPY root/ / 22 | 23 | # ports and volumes 24 | VOLUME ["/config","/usr/share/snmp/mibs"] 25 | 26 | ENTRYPOINT ["/usr/bin/python3", "root/easy_influx.py"] -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ben Dews 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bendews/EasyInflux-Docker/834d89ce3d216f0b42b37be8bbfa2c0b6a543d80/Preview.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EasyInflux 2 | 3 | [![Docker pull](https://img.shields.io/docker/pulls/bendews/easyinflux.svg)](https://hub.docker.com/r/bendews/easyinflux/) 4 | [![Github issues](https://img.shields.io/github/issues/bendews/EasyInflux-Docker.svg)](https://github.com/bendews/EasyInflux-Docker/issues) [![License](https://img.shields.io/github/license/bendews/EasyInflux-Docker.svg)](https://github.com/bendews/EasyInflux-Docker/blob/master/LICENSE) 5 | 6 | A [Docker](https://www.docker.com) container that simplifies the collection of many common SNMP and IPMI data points to insert into InfluxDB. 7 | 8 | Initial inspiration drawn from the work done by [dencur](https://www.reddit.com/u/dencur) in [this blog post](https://denlab.io/setup-a-wicked-grafana-dashboard-to-monitor-practically-anything/) 9 | 10 | [View image on Docker Hub](https://hub.docker.com/r/bendews/easyinflux/) 11 | 12 | ##### Preview of supported stats 13 | 14 | ![Grafana Preview with EasyInflux stats](https://raw.githubusercontent.com/bendews/EasyInflux-Docker/master/Preview.gif) 15 | 16 | ## Getting started 17 | EasyInflux is... easy! 18 | All you need: 19 | * Configuration file 20 | * VMWare SNMP MIB files from [VMWare KB 1013445](https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1013445) (Only if monitoring ESXi hosts) 21 | 22 | 23 | ``` 24 | docker run -d --name easy-influx \ 25 | -v [PATH TO CONFIG FILE]:/config/config.yaml:ro \ 26 | -v [PATH TO MIB FOLDER]:/usr/share/snmp/mibs:ro \ 27 | bendews/easyinflux 28 | ``` 29 | 30 | 31 | 32 | ## Configuration 33 | A sample configuration file is located at `root/sampleConfig.yaml`. 34 | Please view the sample configuration file to get a better understanding of its options. 35 | Option descriptions are as follows: 36 | 37 | #### REQUIRED - influxdb 38 | |Key |Description | 39 | |:--------------|:-------------------------------------------------------------------------------------------------------------------| 40 | |hostname |The hostname (or IP address) of the influxDB Server | 41 | |port |The API port of the influxDB server (usually 8086) | 42 | |database |The database for EasyInflux to write data to (a new database is recommended) | 43 | |insert_interval|The time interval in seconds that values are collected and sent to InfluxDB (a value of 30 or higher is recommended)| 44 | #### Optional - esxi_hosts 45 | |Key |Description | 46 | :---------------|:-------------------------------------------------------------------------------------------------------------------| 47 | |hostname |The hostname (or IP address) of the ESXi Server | 48 | |snmp_community |The SNMP community string for this host | 49 | |snmp_version |The SNMP version for this host ("1" or "2c" supported at this time) | 50 | #### Optional - synology_hosts 51 | |Key |Description | 52 | :---------------|:-------------------------------------------------------------------------------------------------------------------| 53 | |hostname |The hostname (or IP address) of the Synology Server | 54 | |snmp_community |The SNMP community string for this host | 55 | |snmp_version |The SNMP version for this host ("1" or "2c" supported at this time) | 56 | |volumes |The volumes on the Synology host to be reported ("volume1", "volume2" etc.) | 57 | #### Optional - ipmi_hosts 58 | |Key |Description | 59 | :---------------|:-------------------------------------------------------------------------------------------------------------------| 60 | |hostname |The hostname (or IP address) of the IPMI supported device | 61 | |ipmi_username |The IPMI username for this host | 62 | |ipmi_password |The IPMI password for this host | 63 | #### Optional - ups_hosts 64 | |Key |Description | 65 | :---------------|:-------------------------------------------------------------------------------------------------------------------| 66 | |hostname |The hostname (or IP address) of the UPS SNMP interface | 67 | |snmp_community |The SNMP community string for this host | 68 | |snmp_version |The SNMP version for this host ("1" or "2c" supported at this time) | 69 | 70 | Note that **ALL** values should be string escaped (I.E, be within "quotation marks") 71 | 72 | ## [License](https://github.com/bendews/EasyInflux-Docker/blob/master/LICENSE.txt) -------------------------------------------------------------------------------- /root/config/configSample.yaml: -------------------------------------------------------------------------------- 1 | influxdb: 2 | hostname: "InfluxDB.company.com" 3 | port: "2003" 4 | database: "easy_influx" 5 | insert_interval: "30" 6 | 7 | esxi_hosts: 8 | - hostname: "ESXi-01.company.com" 9 | snmp_community: "public" 10 | snmp_version: "2c" 11 | - hostname: "ESXi-01.company.com" 12 | snmp_community: "public" 13 | snmp_version: "2c" 14 | - hostname: "ESXi-03.company.com" 15 | snmp_community: "public" 16 | snmp_version: "2c" 17 | 18 | synology_hosts: 19 | - hostname: "Synology-01.company.com" 20 | snmp_community: "public" 21 | snmp_version: "2c" 22 | volumes: 23 | - "volume1" 24 | - "volume2" 25 | - "volume3" 26 | 27 | ipmi_hosts: 28 | - hostname: "Dell-iDRAC.company.com" 29 | ipmi_username: "root" 30 | ipmi_password: "password123" 31 | - hostname: "HP-iLO.company.com" 32 | ipmi_username: "Administrator" 33 | ipmi_password: "password123" 34 | 35 | ups_hosts: 36 | - hostname: "UPS.company.com" 37 | snmp_community: "public" 38 | snmp_version: "1" -------------------------------------------------------------------------------- /root/root/easy_influx.py: -------------------------------------------------------------------------------- 1 | ################################ 2 | # - Ben Dews 3 | # - bendews.com 4 | # - 02/01/2017 5 | # - Main loop for EasyInflux script 6 | ################################ 7 | 8 | import yaml 9 | import requests 10 | import logging 11 | import os 12 | import time 13 | import datetime 14 | import math 15 | 16 | import esx_snmp 17 | import synology_snmp 18 | import ups_snmp 19 | import misc_ipmi 20 | 21 | import host_classes as host 22 | import handlers as func 23 | 24 | 25 | currentDirectory = os.path.dirname(os.path.abspath(__file__)) 26 | logging.basicConfig(level=logging.DEBUG) 27 | 28 | # Round unix time to closest interval period 29 | def roundTimeToSeconds(unixTime,secondsToRound): 30 | return int(round(unixTime / secondsToRound) * secondsToRound) 31 | 32 | # Convert list of InfluxDB data into string for POST request 33 | def listToInfluxDBString(list): 34 | length = len(list) - 1 35 | influxDBString = "" 36 | if length == 0: 37 | influxDBString = list[0] 38 | else: 39 | for value in list[:-1]: 40 | influxDBString = influxDBString+value+"\n" 41 | pass 42 | influxDBString = influxDBString+list[length] 43 | return influxDBString 44 | 45 | # Load config file 46 | with open(currentDirectory+"/../config/config.yaml", 'r') as stream: 47 | try: 48 | config = yaml.load(stream) 49 | except yaml.YAMLError as err: 50 | logging.error(err) 51 | exit(1) 52 | try: 53 | # Assign InfluxDB Variables 54 | INFLUXDB_CONFIG = config["influxdb"] 55 | # Interval to run script 56 | INSERT_INTERVAL = float(INFLUXDB_CONFIG["insert_interval"]) 57 | # hostname of influxDB server 58 | INFLUX_SERVER = str(INFLUXDB_CONFIG["hostname"]) 59 | # API port of influxDB server 60 | INFLUX_PORT = str(INFLUXDB_CONFIG["port"]) 61 | # Database for values to be inserted into 62 | INFLUX_DB = str(INFLUXDB_CONFIG["database"]) 63 | # URL used for POST request 64 | INFLUX_URL = "http://"+INFLUX_SERVER+":"+INFLUX_PORT+"/write?db="+INFLUX_DB+"&precision=s" 65 | except (KeyError,TypeError,NameError) as err: 66 | logging.error("Please check your configuration file! An error occurred whilst parsing:",err) 67 | exit(1) 68 | 69 | 70 | 71 | while True: 72 | # Round insert timestamp to interval period 73 | timeStamp = roundTimeToSeconds(time.time(),INSERT_INTERVAL) 74 | logging.debug("Gathering statistics every "+str(INSERT_INTERVAL)+" seconds") 75 | logging.debug("Actual Time:"+datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')) 76 | logging.debug("Timestamp for data:"+datetime.datetime.fromtimestamp(timeStamp).strftime('%Y-%m-%d %H:%M:%S')) 77 | 78 | # Assign hosts in configuration to Lists 79 | ESXI_HOSTS = config.get('esxi_hosts',[]) 80 | IPMI_HOSTS = config.get('ipmi_hosts',[]) 81 | SYNOLOGY_HOSTS = config.get('synology_hosts',[]) 82 | UPS_HOSTS = config.get('ups_hosts',[]) 83 | 84 | valueList = [] 85 | 86 | # Loop through each host and gather data 87 | for hostData in ESXI_HOSTS: 88 | esxHost = host.EsxHost(hostData["hostname"],hostData["snmp_community"],hostData["snmp_version"]) 89 | valueList = esx_snmp.procLoad(esxHost,valueList,timeStamp) 90 | valueList = esx_snmp.VMList(esxHost,valueList,timeStamp) 91 | 92 | for hostData in IPMI_HOSTS: 93 | ipmiHost = host.IpmiHost(hostData["hostname"],hostData["ipmi_username"],hostData["ipmi_password"]) 94 | valueList = misc_ipmi.fanTempMeasure(ipmiHost,valueList,timeStamp) 95 | 96 | for hostData in SYNOLOGY_HOSTS: 97 | volumes = hostData.get('volumes',[]) 98 | synHost = host.SynologyHost(hostData["hostname"],hostData["snmp_community"],hostData["snmp_version"],volumes) 99 | valueList = synology_snmp.diskUsage(synHost,valueList,timeStamp) 100 | valueList = synology_snmp.diskTemp(synHost,valueList,timeStamp) 101 | 102 | for hostData in UPS_HOSTS: 103 | upsHost = host.UpsHost(hostData["hostname"],hostData["snmp_community"],hostData["snmp_version"]) 104 | valueList = ups_snmp.upsPower(upsHost,valueList,timeStamp) 105 | 106 | 107 | if valueList: 108 | # Convert list of insert data into string for POST request 109 | INFLUX_DATA = listToInfluxDBString(valueList) 110 | # Print collected data 111 | logging.debug(INFLUX_DATA) 112 | # Post data to InfluxDB 113 | requests.post(INFLUX_URL, data=INFLUX_DATA,headers={'Content-Type': 'application/octet-stream'},timeout = 3) 114 | 115 | # Delay data collection loop to match interval period 116 | timeToSleep = INSERT_INTERVAL - ((time.time() - timeStamp) % INSERT_INTERVAL) 117 | logging.info("Statistics gathered, sleeping for "+str(timeToSleep)+" seconds") 118 | time.sleep(timeToSleep) 119 | pass -------------------------------------------------------------------------------- /root/root/esx_snmp.py: -------------------------------------------------------------------------------- 1 | ################################ 2 | # - Ben Dews 3 | # - bendews.com 4 | # - 30/12/2016 5 | # - Script to get ESXi SNMP statistics and insert to InfluxDB 6 | ################################ 7 | import subprocess 8 | import requests 9 | import re 10 | 11 | import handlers as func 12 | 13 | def procLoad(esxHost,valueInsertList,timeStamp): 14 | procOID = ".1.3.6.1.2.1.25.3.3.1.2" 15 | i = 0 16 | 17 | hostname = esxHost.hostname 18 | snmpCommunity = esxHost.snmpCommunity 19 | snmpVersion = esxHost.snmpVersion 20 | 21 | 22 | output = func.snmpWalk(hostname,snmpCommunity,snmpVersion,procOID) 23 | for line in output: 24 | if procOID in line: 25 | i += 1 26 | cpuCore = "cpu"+str(i) 27 | result = re.findall(r'\: (\d*)',line) 28 | if result: 29 | loadValue = str(result[0]) 30 | data_procLoad = [hostname,cpuCore,"cpu_load",loadValue] 31 | valueInsertList.append(func.getPostData(data_procLoad,timeStamp)) 32 | pass 33 | pass 34 | return valueInsertList 35 | 36 | def VMList(esxHost,valueInsertList,timeStamp): 37 | vmInfoOID = ".1.3.6.1.4.1.6876.2.1.1" 38 | vmLabelOID = vmInfoOID+".2" 39 | vmStateOID = vmInfoOID+".6" 40 | vmNames = [] 41 | powerStates = [] 42 | 43 | hostname = esxHost.hostname 44 | snmpCommunity = esxHost.snmpCommunity 45 | snmpVersion = esxHost.snmpVersion 46 | 47 | output = func.snmpWalk(hostname,snmpCommunity,snmpVersion,vmInfoOID) 48 | 49 | for line in output: 50 | if vmLabelOID in line: 51 | result = re.findall(r'\: (.*)',line) 52 | result = str(result[0]) 53 | result = result.replace('"','') 54 | vmNames.append(result) 55 | pass 56 | if vmStateOID in line: 57 | result = re.findall(r'\: (.*)',line) 58 | result = str(result[0]) 59 | result = result.replace('"','') 60 | powerStates.append(result) 61 | pass 62 | pass 63 | for name,state in zip(vmNames,powerStates): 64 | binaryState = 1 if state =="powered on" else 0 65 | data_VMStates = [hostname,name,"vm_state",binaryState] 66 | valueInsertList.append(func.getPostData(data_VMStates,timeStamp)) 67 | pass 68 | return valueInsertList 69 | -------------------------------------------------------------------------------- /root/root/handlers.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import requests 3 | 4 | def getPostData(measurementData,timeStamp): 5 | host = str(measurementData[0]).replace(" ", "") 6 | device = str(measurementData[1]).replace(" ", "") 7 | item = str(measurementData[2]).replace(" ", "") 8 | value = str(measurementData[3]).replace(" ", "") 9 | 10 | data = item+",device="+device+",host="+host+" value="+value+" "+str(timeStamp) 11 | return(data) 12 | pass 13 | 14 | def snmpWalk(SNMP_SERVER,SNMP_COMMUNITY,SNMP_VERSION,oid): 15 | SNMP_VERSION = str(SNMP_VERSION) 16 | 17 | p = subprocess.run(["snmpwalk", "-O", "fn", "-v", SNMP_VERSION, "-c", SNMP_COMMUNITY, SNMP_SERVER, oid], stdout=subprocess.PIPE) 18 | output = p.stdout.decode('utf8').splitlines() 19 | return output 20 | pass 21 | 22 | def ipmiTool(hostname,username,password): 23 | IPMI_SERVER = hostname 24 | IPMI_USERNAME = username 25 | IPMI_PASSWORD = password 26 | 27 | p = subprocess.run(["ipmitool", "-H", IPMI_SERVER, "-U", IPMI_USERNAME, "-P", IPMI_PASSWORD, "-I", "lanplus", "sdr", "list", "full"], stdout=subprocess.PIPE) 28 | output = p.stdout.decode('utf8').splitlines() 29 | 30 | return output 31 | pass -------------------------------------------------------------------------------- /root/root/host_classes.py: -------------------------------------------------------------------------------- 1 | # Base Class 2 | class Host: 3 | # Init Class Object 4 | def __init__(self, hostname): 5 | self.hostname = hostname 6 | def hostname(self): 7 | print(self.hostname) 8 | 9 | # Base SNMP Class 10 | class SnmpHost(Host): 11 | # Init Class Object 12 | def __init__(self, hostname, snmpCommunity, snmpVersion): 13 | Host.__init__(self, hostname) 14 | self.snmpCommunity = snmpCommunity 15 | self.snmpVersion = snmpVersion 16 | def snmpCommunity(self): 17 | print(self.snmpCommunity) 18 | def snmpVersion(self): 19 | print(self.snmpVersion) 20 | 21 | # Base IPMI Class 22 | class IpmiHost(Host): 23 | # Init Class Object 24 | def __init__(self, hostname, username, password): 25 | Host.__init__(self, hostname) 26 | self.username = username 27 | self.password = password 28 | def username(self): 29 | print(self.username) 30 | def password(self): 31 | print(self.password) 32 | 33 | # ESX Host Class 34 | class EsxHost(SnmpHost): 35 | # Init Class Object 36 | def __init__(self, hostname, snmpCommunity, snmpVersion): 37 | SnmpHost.__init__(self, hostname, snmpCommunity,snmpVersion) 38 | 39 | # UPS Host Class 40 | class UpsHost(SnmpHost): 41 | # Init Class Object 42 | def __init__(self, hostname, snmpCommunity, snmpVersion): 43 | SnmpHost.__init__(self, hostname, snmpCommunity,snmpVersion) 44 | 45 | # Synology Host Class 46 | class SynologyHost: 47 | # Init Class Object 48 | def __init__(self, hostname, snmpCommunity, snmpVersion, volumeList): 49 | SnmpHost.__init__(self, hostname, snmpCommunity,snmpVersion) 50 | self.volumeList = volumeList 51 | def volumeList(self): 52 | print(self.volumeList) -------------------------------------------------------------------------------- /root/root/misc_ipmi.py: -------------------------------------------------------------------------------- 1 | ################################ 2 | # - Ben Dews 3 | # - bendews.com 4 | # - 30/12/2016 5 | # - Script to get IPMI statistics and insert to InfluxDB 6 | ################################ 7 | import subprocess 8 | import requests 9 | import re 10 | 11 | import handlers as func 12 | 13 | def fanTempMeasure(ipmiHost,valueInsertList,timeStamp): 14 | measurements = [] 15 | 16 | hostname = ipmiHost.hostname 17 | username = ipmiHost.username 18 | password = ipmiHost.password 19 | 20 | output = func.ipmiTool(hostname,username,password) 21 | 22 | for line in output: 23 | line = line.split("|") 24 | for idx,value in enumerate(line): 25 | # print(value.strip()) 26 | value = re.findall(r'^(\d*\.?\d*) ',value.strip()) 27 | if value: 28 | device = line[idx-1].strip() 29 | value = value[0] 30 | measurements.append((device,value)) 31 | pass 32 | 33 | for device,value in measurements: 34 | # print(device,value) 35 | device = device.replace(" ", "") 36 | value = value.replace(" ", "") 37 | if "fan" in device.lower(): 38 | item = "fan_rpm" 39 | else: 40 | item = "temperature" 41 | 42 | data_fanTemp = [hostname,device,item,value] 43 | valueInsertList.append(func.getPostData(data_fanTemp,timeStamp)) 44 | pass 45 | return valueInsertList 46 | 47 | 48 | -------------------------------------------------------------------------------- /root/root/synology_snmp.py: -------------------------------------------------------------------------------- 1 | ################################ 2 | # - Ben Dews 3 | # - bendews.com 4 | # - 30/12/2016 5 | # - Script to get Synology SNMP statistics and insert to InfluxDB 6 | ################################ 7 | import subprocess 8 | import requests 9 | import re 10 | 11 | import handlers as func 12 | 13 | def sizeInGB(totalSize,allocSize): 14 | result = (totalSize*allocSize)/1024/1024/1024 15 | result = "%.4f" % result 16 | return result 17 | pass 18 | 19 | def diskUsage(synHost,valueInsertList,timeStamp): 20 | storageInfoOID = ".1.3.6.1.2.1.25.2.3.1" 21 | storageLabelOID = storageInfoOID+".3" 22 | storageAllocOID = storageInfoOID+".4" 23 | storageTotalOID = storageInfoOID+".5" 24 | storageUsedOID = storageInfoOID+".6" 25 | disks = [] 26 | allocationSize = [] 27 | storageSize = [] 28 | storageUsed = [] 29 | 30 | 31 | hostname = synHost.hostname 32 | snmpCommunity = synHost.snmpCommunity 33 | snmpVersion = synHost.snmpVersion 34 | volumeList = synHost.volumeList 35 | 36 | output = func.snmpWalk(hostname,snmpCommunity,snmpVersion,storageInfoOID) 37 | 38 | for line in output: 39 | # Storage Label 40 | if ".1.3.6.1.2.1.25.2.3.1.3" in line: 41 | result = re.findall(r'\: (.*)',line) 42 | disks.append(str(result[0])) 43 | pass 44 | # Allocation Size 45 | if ".1.3.6.1.2.1.25.2.3.1.4" in line: 46 | result = re.findall(r'\: (\d*)',line) 47 | allocationSize.append(int(result[0])) 48 | pass 49 | # Storage total size 50 | if ".1.3.6.1.2.1.25.2.3.1.5" in line: 51 | result = re.findall(r'\: (\d*)',line) 52 | storageSize.append(int(result[0])) 53 | pass 54 | # Storage used 55 | if ".1.3.6.1.2.1.25.2.3.1.6" in line: 56 | result = re.findall(r'\: (\d*)',line) 57 | storageUsed.append(int(result[0])) 58 | pass 59 | pass 60 | 61 | for disk,allocSize,storSize,storUsed in zip(disks,allocationSize,storageSize,storageUsed): 62 | totalInTB = sizeInGB(storSize,allocSize) 63 | usedInTB = sizeInGB(storUsed,allocSize) 64 | for volume in volumeList: 65 | if volume in disk: 66 | data_totalInTB = [hostname,volume,"total_storage",totalInTB] 67 | valueInsertList.append(func.getPostData(data_totalInTB,timeStamp)) 68 | data_usedInTB = [hostname,volume,"used_storage",usedInTB] 69 | valueInsertList.append(func.getPostData(data_usedInTB,timeStamp)) 70 | pass 71 | pass 72 | pass 73 | return valueInsertList 74 | 75 | def diskTemp(synHost,valueInsertList,timeStamp): 76 | diskInfoOID = ".1.3.6.1.4.1.6574.2.1.1" 77 | diskLabelOID = diskInfoOID+".2" 78 | diskTempOID = diskInfoOID+".6" 79 | disks = [] 80 | temps = [] 81 | 82 | 83 | hostname = synHost.hostname 84 | snmpCommunity = synHost.snmpCommunity 85 | snmpVersion = synHost.snmpVersion 86 | volumeList = synHost.volumeList 87 | 88 | output = func.snmpWalk(hostname,snmpCommunity,snmpVersion,diskInfoOID) 89 | 90 | for line in output: 91 | if diskLabelOID in line: 92 | result = re.findall(r'\"(.*)\"',line) 93 | disks.append(result[0]) 94 | pass 95 | if diskTempOID in line: 96 | result = re.findall(r'\: (\d*)',line) 97 | temps.append(result[0]) 98 | pass 99 | pass 100 | for disk,temp in zip(disks,temps): 101 | data_diskTemp = [hostname,disk,"temperature",temp] 102 | valueInsertList.append(func.getPostData(data_diskTemp,timeStamp)) 103 | pass 104 | return valueInsertList 105 | -------------------------------------------------------------------------------- /root/root/ups_snmp.py: -------------------------------------------------------------------------------- 1 | ################################ 2 | # - Ben Dews 3 | # - bendews.com 4 | # - 30/12/2016 5 | # - Script to get UPS SNMP and insert to InfluxDB 6 | ################################ 7 | import subprocess 8 | import requests 9 | import re 10 | 11 | import handlers as func 12 | 13 | def upsPower(upsHost,valueInsertList,timeStamp): 14 | upsInfoOID = "1.3.6.1.2.1.33.1" 15 | upsWattsOID = upsInfoOID+".4.4.1.4.1" 16 | upsMinutesOID = upsInfoOID+".2.3.0" 17 | upsChargeOID = upsInfoOID+".2.4.0" 18 | 19 | hostname = upsHost.hostname 20 | snmpCommunity = upsHost.snmpCommunity 21 | snmpVersion = upsHost.snmpVersion 22 | 23 | output = func.snmpWalk(hostname,snmpCommunity,snmpVersion,upsInfoOID) 24 | 25 | for line in output: 26 | if upsWattsOID in line: 27 | result = re.findall(r'\: (\d*)',line) 28 | upsPower = str(result[0]) 29 | data_upsPower = [hostname,"ActivePower","ups_power",upsPower] 30 | valueInsertList.append(func.getPostData(data_upsPower,timeStamp)) 31 | pass 32 | if upsMinutesOID in line: 33 | result = re.findall(r'\: (\d*)',line) 34 | upsPower = str(result[0]) 35 | data_upsPower = [hostname,"MinutesRemaining","ups_power",upsPower] 36 | valueInsertList.append(func.getPostData(data_upsPower,timeStamp)) 37 | pass 38 | if upsChargeOID in line: 39 | result = re.findall(r'\: (\d*)',line) 40 | upsPower = str(result[0]) 41 | data_upsPower = [hostname,"ChargePercent","ups_power",upsPower] 42 | valueInsertList.append(func.getPostData(data_upsPower,timeStamp)) 43 | pass 44 | pass 45 | return valueInsertList 46 | --------------------------------------------------------------------------------