moving plugins & NEWDEV

This commit is contained in:
Jokob-sk
2023-07-09 22:19:40 +10:00
parent acb756a871
commit 770d9bfe4a
40 changed files with 613 additions and 72 deletions

View File

@@ -0,0 +1,12 @@
## Overview
A simple sample plugin allowing for monitoring web services or urls. The status code corresponds to the commonly used [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
### Usage
- The user can specify which services (websites) to monitor via the `WEBMON_urls_to_check` setting.
### Notes
- Setting `(WEBMON_)SQL_internet_ip` is not used and specified for demonstration purposes only.
- Parameters `macs` and `internet_ip` in the `config.json` file are not used and specified for demonstration purposes only.

View File

@@ -0,0 +1,383 @@
{
"code_name": "website_monitor",
"unique_prefix": "WEBMON",
"enabled": true,
"data_source": "python-script",
"localized": ["display_name", "description", "icon"],
"display_name" : [{
"language_code":"en_us",
"string" : "Website monitor"
}],
"icon":[{
"language_code":"en_us",
"string" : "<i class=\"fa-solid fa-globe\"></i>"
}],
"description": [{
"language_code":"en_us",
"string" : "This plugin is to monitor status changes of services or websites."
}],
"params" : [{
"name" : "macs",
"type" : "sql",
"value" : "SELECT dev_MAC from DEVICES"
},
{
"name" : "urls",
"type" : "setting",
"value" : "WEBMON_urls_to_check"
},
{
"name" : "internet_ip",
"type" : "setting",
"value" : "WEBMON_SQL_internet_ip"
}],
"database_column_definitions":
[
{
"column": "Index",
"css_classes": "col-sm-2",
"show": false,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "N/A"
}]
} ,
{
"column": "Plugin",
"css_classes": "col-sm-2",
"show": false,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "N/A"
}]
},
{
"column": "Object_PrimaryID",
"css_classes": "col-sm-2",
"show": true,
"type": "url",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Monitored URL"
}]
},
{
"column": "Object_SecondaryID",
"css_classes": "col-sm-2",
"show": false,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "N/A"
}]
} ,
{
"column": "DateTimeCreated",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Created"
}]
},
{
"column": "DateTimeChanged",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Changed"
}]
},
{
"column": "Watched_Value1",
"css_classes": "col-sm-2",
"show": true,
"type": "threshold",
"default_value":"",
"options": [
{
"maximum": 199,
"hexColor": "#792D86"
},
{
"maximum": 299,
"hexColor": "#5B862D"
},
{
"maximum": 399,
"hexColor": "#7D862D"
},
{
"maximum": 499,
"hexColor": "#BF6440"
},
{
"maximum": 599,
"hexColor": "#D33115"
}
],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Status code"
}]
},
{
"column": "Watched_Value2",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Latency"
}]
},
{
"column": "Watched_Value3",
"css_classes": "col-sm-2",
"show": false,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "N/A"
}]
} ,
{
"column": "Watched_Value4",
"css_classes": "col-sm-2",
"show": false,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "N/A"
}]
} ,
{
"column": "UserData",
"css_classes": "col-sm-2",
"show": true,
"type": "textboxsave",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Comments"
}]
},
{
"column": "Status",
"css_classes": "col-sm-1",
"show": true,
"type": "replace",
"default_value":"",
"options": [
{
"equals": "watched-not-changed",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
},
{
"equals": "watched-changed",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
},
{
"equals": "new",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
}
],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Status"
}]
},
{
"column": "Extra",
"css_classes": "col-sm-3",
"show": false,
"type": "label",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "Extra"
}]
}
],
"settings":[
{
"function": "RUN",
"type": "selecttext",
"default_value":"disabled",
"options": ["disabled", "once", "schedule", "always_after_scan", "on_new_device"],
"localized": ["name", "description"],
"name" :[{
"language_code":"en_us",
"string" : "When to run"
}],
"description": [{
"language_code":"en_us",
"string" : "Enable a regular scan of your services. If you select <code>schedule</code> the scheduling settings from below are applied. If you select <code>once</code> the scan is run only once on start of the application (container) for the time specified in <a href=\"#WEBMON_RUN_TIMEOUT\"><code>WEBMON_RUN_TIMEOUT</code> setting</a>."
}]
},
{
"function": "CMD",
"type": "text",
"default_value":"python3 /home/pi/pialert/pialert/plugins/website_monitor/script.py urls={urls}",
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Command"
}],
"description": [{
"language_code":"en_us",
"string" : "Command to run"
}]
},
{
"function": "RUN_SCHD",
"type": "text",
"default_value":"0 2 * * *",
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Schedule"
}],
"description": [{
"language_code":"en_us",
"string" : "Only enabled if you select <code>schedule</code> in the <a href=\"#WEBMON_RUN\"><code>WEBMON_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format (e.g. validate at <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). For example entering <code>0 4 * * *</code> will run the scan after 4 am in the <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> you set above</a>. Will be run NEXT time the time passes."
}]
},
{
"function": "API_SQL",
"type": "text",
"default_value":"SELECT * FROM plugin_website_monitor",
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "API endpoint (not implemented)"
}],
"description": [{
"language_code":"en_us",
"string" : "You can specify a custom SQL query which will generate a JSON file and then expose it via the <a href=\"/api/plugin_website_monitor.json\" target=\"_blank\"><code>plugin_website_monitor.json</code> file endpoint</a>."
}]
},
{
"function": "RUN_TIMEOUT",
"type": "integer",
"default_value":5,
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Run timeout"
},
{
"language_code":"de_de",
"string" : "Wartezeit"
}],
"description": [{
"language_code":"en_us",
"string" : "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
}]
},
{
"function": "WATCH",
"type": "multiselect",
"default_value":["Watched_Value1"],
"options": ["Watched_Value1","Watched_Value2","Watched_Value3","Watched_Value4"],
"localized": ["name", "description"],
"name" :[{
"language_code":"en_us",
"string" : "Watched"
}] ,
"description":[{
"language_code":"en_us",
"string" : "Send a notification if selected values change. Use <code>CTRL + Click</code> to select/deselect. <ul> <li><code>Watched_Value1</code> is response status code (e.g.: 200, 404)</li><li><code>Watched_Value2</code> is Latency (not recommended)</li><li><code>Watched_Value3</code> unused </li><li><code>Watched_Value4</code> unused </li></ul>"
}]
},
{
"function": "REPORT_ON",
"type": "multiselect",
"default_value":["new","watched-changed"],
"options": ["new","watched-changed","watched-not-changed"],
"localized": ["name", "description"],
"name" :[{
"language_code":"en_us",
"string" : "Report on"
}] ,
"description":[{
"language_code":"en_us",
"string" : "Send a notification only on these statuses. <code>new</code> means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. <code>watched-changed</code> means that selected <code>Watched_ValueN</code> columns changed."
}]
},
{
"function": "urls_to_check",
"type": "list",
"default_value":["https://google.com", "https://duck.com"],
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Arguments"
}],
"description": [{
"language_code":"en_us",
"string" : "Services to watch. Enter full URL, e.g. <code>https://google.com</code>. The values from this setting will be used to replace the <code>{urls}</code> wildcard in the <code>WEBMON_CMD</code> setting."
}]
},
{
"function": "SQL_internet_ip",
"type": "readonly",
"default_value":"SELECT dev_LastIP FROM Devices WHERE dev_MAC = 'Internet'",
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Helper variable"
}],
"description": [{
"language_code":"en_us",
"string" : "Unused setting - for demonstration only. Getting the IP address of the Router / Internet. "
}]
}
]
}

View File

@@ -0,0 +1,148 @@
#!/usr/bin/env python
# Based on the work of https://github.com/leiweibau/Pi.Alert
# python3 /home/pi/pialert/pialert/plugins/website_monitor/script.py urls=http://google.com,http://bing.com
from __future__ import unicode_literals
from time import sleep, time, strftime
import requests
import pathlib
import argparse
import io
#import smtplib
import sys
#from smtp_config import sender, password, receivers, host, port
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import pwd
import os
curPath = str(pathlib.Path(__file__).parent.resolve())
log_file = curPath + '/script.log'
last_run = curPath + '/last_result.log'
print(last_run)
# Workflow
def main():
parser = argparse.ArgumentParser(description='Simple URL monitoring tool')
parser.add_argument('urls', action="store", help="urls to check separated by ','")
values = parser.parse_args()
if values.urls:
with open(last_run, 'w') as last_run_logfile:
# empty file
last_run_logfile.write("")
service_monitoring(values.urls.split('=')[1].split(','))
else:
return
# -----------------------------------------------------------------------------
def service_monitoring_log(site, status, latency):
# global monitor_logfile
# Log status message to log file
with open(log_file, 'a') as monitor_logfile:
monitor_logfile.write("{} | {} | {} | {}\n".format(strftime("%Y-%m-%d %H:%M:%S"),
site,
status,
latency,
)
)
with open(last_run, 'a') as last_run_logfile:
# https://www.duckduckgo.com|192.168.0.1|2023-01-02 15:56:30|200|0.9898|null|null|Best search engine|null
last_run_logfile.write("{}|{}|{}|{}|{}|{}|{}|{}|{}\n".format(
site,
'null',
strftime("%Y-%m-%d %H:%M:%S"),
status,
latency,
'null',
'null',
'null',
'null',
)
)
# -----------------------------------------------------------------------------
def check_services_health(site):
# Enable self signed SSL
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
"""Send GET request to input site and return status code"""
try:
resp = requests.get(site, verify=False, timeout=10)
latency = resp.elapsed
latency_str = str(latency)
latency_str_seconds = latency_str.split(":")
format_latency_str = latency_str_seconds[2]
if format_latency_str[0] == "0" and format_latency_str[1] != "." :
format_latency_str = format_latency_str[1:]
return resp.status_code, format_latency_str
except requests.exceptions.SSLError:
pass
except:
latency = "99999"
return 503, latency
# -----------------------------------------------------------------------------
def get_username():
return pwd.getpwuid(os.getuid())[0]
# -----------------------------------------------------------------------------
def service_monitoring(urls):
# Empty Log and write new header
print("Prepare Services Monitoring")
print("... Prepare Logfile")
with open(log_file, 'w') as monitor_logfile:
monitor_logfile.write("Pi.Alert [Prototype]:\n---------------------------------------------------------\n")
monitor_logfile.write("Current User: %s \n\n" % get_username())
monitor_logfile.write("Monitor Web-Services\n")
monitor_logfile.write("Timestamp: " + strftime("%Y-%m-%d %H:%M:%S") + "\n")
monitor_logfile.close()
print("... Get Services List")
sites = urls
print("Start Services Monitoring")
with open(log_file, 'a') as monitor_logfile:
monitor_logfile.write("\nStart Services Monitoring\n\n| Timestamp | URL | StatusCode | ResponseTime |\n-----------------------------------------------\n")
monitor_logfile.close()
while sites:
for site in sites:
status,latency = check_services_health(site)
scantime = strftime("%Y-%m-%d %H:%M:%S")
# Debugging
# print("{} - {} STATUS: {} ResponseTime: {}".format(strftime("%Y-%m-%d %H:%M:%S"),
# site,
# status,
# latency)
# )
# Write Logfile
service_monitoring_log(site, status, latency)
sys.stdout.flush()
break
else:
with open(log_file, 'a') as monitor_logfile:
monitor_logfile.write("\n\nNo site(s) to monitor!")
monitor_logfile.close()
#===============================================================================
# BEGIN
#===============================================================================
if __name__ == '__main__':
sys.exit(main())