initial upload of version 3.1.1 which uses the new plugin API
This commit is contained in:
parent
0152860b55
commit
c0f4490b89
15
README.md
15
README.md
@ -1,16 +1,18 @@
|
||||
# Nextcloud CheckMK Special Agent
|
||||
Monitors various aspects of Nextcloud instances like state, quota and disk usage of all users, number of apps with available updates, database php opcache hit rate and so on.
|
||||
Gives additional information regarding versions of Nextcloud, database, number of storages and active users etc.
|
||||
Tested with Nextcloud 25/26/27/28.
|
||||
Tested only with MySQL/MariaDB as database backend.
|
||||
Tested only with Nextcloud versions 29/30
|
||||
Tested only with MariaDB as database backend
|
||||
The whole plugin is now migrated to the new plugin API version, introduced with CheckMK 2.3
|
||||
Feel free to report other working environments.
|
||||
|
||||
|
||||
Upgrade from older MKPs (before 2.4.0):
|
||||
If you upgrade from a already installed version before 2.4.0, you have to re-create your rules for the "Nextcloud Server Information" (reason: massive parameter changes).
|
||||
Steps to accomplish this without problems:
|
||||
Upgrade from older MKPs (before 3.1.1):
|
||||
|
||||
1. Take a screenshot of your settings in the above mentioned ruleset
|
||||
If you upgrade from a already installed MKP version before 3.1.0, you have to re-create your rules for the "Nextcloud Server Information" (reason: some parameter changes combined with the migration to the new plugin API).
|
||||
Hint: It is always a good idea to create screenshots from all other Nextcloud rules as well.
|
||||
|
||||
1. Take a screenshot of your settings in the above mentioned rulesets
|
||||
2. Assure that you have access to the passwords/tokens you used within the current rules
|
||||
3. Delete all rules for "Nextcloud Server Information"
|
||||
4. Install and enable the new MKP
|
||||
@ -39,6 +41,7 @@ Version History:
|
||||
--
|
||||
|Date|Version|Changes|
|
||||
|----|-------|-------|
|
||||
|2025/03/30|3.1.1|Migration to the new plugin API version finished, (hopefully) ready for CheckMK version 2.4
|
||||
|2023/01/13|2.5.2|Repackaged only to set the minimum required version back to 2.1.0p1, due to serveral user requests|
|
||||
|2023/01/12|2.5.1|Added versions for apps with available updates|
|
||||
|2023/01/12|2.4.1|Removed Parameter "token", switched to parameter "app password" only|
|
||||
|
@ -1,82 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from pprint import pprint
|
||||
from .agent_based_api.v1 import register, render, Service, Result, State, Metric
|
||||
|
||||
def getStateUpper(levels, value):
|
||||
warn, crit = levels
|
||||
if value >= crit:
|
||||
return State.CRIT
|
||||
if value >= warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
def getStateLower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
if value < warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
def discover_nextcloud_database(section):
|
||||
yield(Service())
|
||||
|
||||
def check_nextcloud_database(params, section):
|
||||
for key in section:
|
||||
if key == "database":
|
||||
opcache_hit_rate = section[key]["opcache_hit_rate"]
|
||||
size = section[key]["size"]
|
||||
type = section[key]["type"]
|
||||
version = section[key]["version"]
|
||||
levels = params["levels_database_opcache_hit_rate"]
|
||||
# create graph for opcache hit rate
|
||||
yield Metric("nc_database_opcache_hit_rate", opcache_hit_rate, levels=levels)
|
||||
# create graph for database size
|
||||
yield Metric("nc_database_size", size)
|
||||
state = getStateLower(levels, opcache_hit_rate)
|
||||
summary = f"PHP OPCache hit rate: {render.percent(opcache_hit_rate)}"
|
||||
if opcache_hit_rate == 0:
|
||||
state = State.UNKNOWN
|
||||
summary = f"PHP OPCache hit rate: 0% - please check if opcache_get_status is enabled"
|
||||
details = f"\nDatabase type: {type}\nDatabase version: {version}\nDatabase size: {render.bytes(size)}"
|
||||
yield(Result(state=state, summary=summary, details=details))
|
||||
|
||||
def parse_nextcloud_database_section(string_table):
|
||||
parsed_data = {
|
||||
"database" : {}
|
||||
}
|
||||
params_list = [
|
||||
"NC_Database_Type",
|
||||
"NC_Database_Version",
|
||||
"NC_Database_Size",
|
||||
"NC_OPCache_Hit_Rate"
|
||||
]
|
||||
for line in string_table:
|
||||
if line[0] in params_list:
|
||||
param = line[0]
|
||||
value = line[1]
|
||||
if param == "NC_Database_Type":
|
||||
parsed_data["database"]["type"] = value
|
||||
elif param == "NC_Database_Version":
|
||||
parsed_data["database"]["version"] = value
|
||||
elif param == "NC_Database_Size":
|
||||
parsed_data["database"]["size"] = int(value)
|
||||
elif param == "NC_OPCache_Hit_Rate":
|
||||
parsed_data["database"]["opcache_hit_rate"] = float(value)
|
||||
return parsed_data
|
||||
|
||||
register.agent_section(
|
||||
name="nextcloud_database",
|
||||
parse_function=parse_nextcloud_database_section,
|
||||
)
|
||||
|
||||
register.check_plugin(
|
||||
name="nextcloud_database",
|
||||
service_name="Nextcloud Database",
|
||||
discovery_function=discover_nextcloud_database,
|
||||
check_function=check_nextcloud_database,
|
||||
check_default_parameters={
|
||||
"levels_database_opcache_hit_rate": (99.7, 99.1),
|
||||
},
|
||||
check_ruleset_name="nextcloud_database",
|
||||
)
|
@ -1,311 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import getopt
|
||||
import sys
|
||||
import requests
|
||||
import urllib3
|
||||
import json
|
||||
import os
|
||||
from pprint import pprint
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
from requests.auth import HTTPBasicAuth
|
||||
import cmk.utils.password_store
|
||||
|
||||
def showUsage():
|
||||
sys.stderr.write("""CheckMK Nextcloud Special Agent
|
||||
|
||||
USAGE: agent_nextcloud_info -u [username] -p [password]
|
||||
OR
|
||||
agent_nextcloud_info -h
|
||||
|
||||
OPTIONS:
|
||||
-H, --hostname Hostname (FQDN or IP) of Nextcloud server
|
||||
-u, --username Username
|
||||
-p, --password App Password
|
||||
-P, --port Port
|
||||
-f, --folder Subfolder if not installed in web root
|
||||
--no-https True|False If "True": Disable HTTPS, use HTTP (not recommended!)
|
||||
--no-cert-check True|False If "True": Disable TLS certificate check (not recommended!)
|
||||
-h, --help Show this help message and exit
|
||||
""")
|
||||
|
||||
# set this to true to produce debug output (this clutters the agent output)
|
||||
# be aware: activating this flag logs very sensitive information to debug files in ~/tmp
|
||||
# !!DO NOT FORGET to delete these files after debugging is done!!
|
||||
|
||||
DEBUG = False
|
||||
|
||||
nc_api_endpoint = "ocs/v2.php/apps/serverinfo/api/v1/info?format=json"
|
||||
nc_api_endpoint_all_users = "ocs/v1.php/cloud/users?format=json"
|
||||
nc_api_endpoint_user = "ocs/v1.php/cloud/users"
|
||||
|
||||
opt_hostname = ""
|
||||
opt_username = ""
|
||||
opt_password = ""
|
||||
opt_port = ""
|
||||
opt_folder = ""
|
||||
opt_no_https = False
|
||||
opt_no_cert_check = False
|
||||
|
||||
short_options = 'hH:u:p:P:f:'
|
||||
long_options = [
|
||||
'hostname=', 'username=', 'password=', 'port=', 'folder=', 'no-https=', 'no-cert-check=', 'help'
|
||||
]
|
||||
|
||||
def logDebug(line):
|
||||
if DEBUG:
|
||||
home_path = os.getenv("HOME")
|
||||
tmp_path = f"{home_path}/tmp"
|
||||
help_file = f"{tmp_path}/nextcloud_{opt_hostname}_{opt_port}_debug.txt"
|
||||
with open(help_file, "a") as file:
|
||||
file.write(line)
|
||||
|
||||
|
||||
def getOptions():
|
||||
global opt_hostname
|
||||
global opt_username
|
||||
global opt_password
|
||||
global opt_port
|
||||
global opt_folder
|
||||
global opt_no_https
|
||||
global opt_no_cert_check
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], short_options, long_options)
|
||||
for opt, arg in opts:
|
||||
if opt in ['-H', '--hostname']:
|
||||
opt_hostname = arg
|
||||
elif opt in ['-u', '--username']:
|
||||
opt_username = arg
|
||||
elif opt in ['-p', '--password']:
|
||||
opt_password = arg
|
||||
elif opt in ['-P', '--port']:
|
||||
opt_port = arg
|
||||
elif opt in ['-f', '--folder']:
|
||||
opt_folder = arg
|
||||
elif opt in ['--no-https']:
|
||||
if arg == 'True':
|
||||
opt_no_https = True
|
||||
else:
|
||||
opt_no_https = False
|
||||
elif opt in ['--no-cert-check']:
|
||||
if arg == 'True':
|
||||
opt_no_cert_check = True
|
||||
else:
|
||||
opt_no_cert_check = False
|
||||
elif opt in ['-h', '--help']:
|
||||
showUsage()
|
||||
sys.exit(0)
|
||||
logDebug(f"getOptions - Number of Arguments: {len(sys.argv)}, Argument List: {str(sys.argv)}\n")
|
||||
|
||||
def showOptions():
|
||||
print(f"Hostname: {opt_hostname}")
|
||||
print(f"Username: {opt_username}")
|
||||
print(f"Password: {opt_password}")
|
||||
print(f"Port: {opt_port}")
|
||||
print(f"Folder: {opt_folder}")
|
||||
print(f"No HTTPS: {opt_no_https}")
|
||||
print(f"No TLS Check: {opt_no_cert_check}")
|
||||
logDebug(f"showOptions - Hostname: {opt_hostname}, Port: {opt_port}, No HTTPS: {opt_no_https}, No Cert Check: {opt_no_cert_check}\n")
|
||||
|
||||
def createUrl(endpoint, hostname, protocol, port, folder):
|
||||
# these parameters are needed, otherwise no information about updates regarding apps and Nextcloud itself are reported (since version 28)
|
||||
params = "skipApps=false&skipUpdate=false"
|
||||
if folder == "":
|
||||
url = f"{protocol}://{hostname}:{port}/{endpoint}"
|
||||
else:
|
||||
url = f"{protocol}://{hostname}:{port}/{folder}/{endpoint}"
|
||||
if endpoint == nc_api_endpoint:
|
||||
url = f"{url}&{params}"
|
||||
logDebug(f"createUrl - Data URL: {url}\n")
|
||||
return url
|
||||
|
||||
def createUrlUser(user, endpoint, hostname, protocol, port, folder):
|
||||
params = "format=json"
|
||||
if folder == "":
|
||||
url = f"{protocol}://{hostname}:{port}/{endpoint}/{user}?{params}"
|
||||
else:
|
||||
url = f"{protocol}://{hostname}:{port}/{folder}/{endpoint}/{user}?{params}"
|
||||
logDebug(f"createUrlUser - User URL: {url}\n")
|
||||
return url
|
||||
|
||||
def getSession(username, secret):
|
||||
session = requests.session()
|
||||
session.cookies.set("SameSite", "Strict")
|
||||
session.auth = (username, secret)
|
||||
session.headers['Accept'] = "application/json"
|
||||
return session
|
||||
|
||||
def getData(session, url, verify):
|
||||
data = {}
|
||||
headers = CaseInsensitiveDict()
|
||||
headers["Accept"] = "application/json"
|
||||
response = session.get(url, headers=headers, verify=verify)
|
||||
status = response.status_code
|
||||
if (status == 200):
|
||||
jsdata = response.text
|
||||
data = json.loads(jsdata) # returns a dictionary
|
||||
return data
|
||||
elif (status == 503):
|
||||
# this code is reported when maintenance mode is on
|
||||
sys.stderr.write(f"Request response code is {response.status_code} with URL {url}, maybe maintenance mode is on?\n")
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.stderr.write(f"Request response code is {response.status_code} with URL {url}\n")
|
||||
sys.exit(1)
|
||||
|
||||
def getDataAllUsers(session, url, verify):
|
||||
headers = CaseInsensitiveDict()
|
||||
headers["Accept"] = "application/json"
|
||||
headers["OCS-APIRequest"] = "true"
|
||||
response = session.get(url, headers=headers, verify=verify)
|
||||
status = response.status_code
|
||||
if (status == 200):
|
||||
jsdata = response.text
|
||||
data = json.loads(jsdata) # returns a dictionary
|
||||
return data
|
||||
else:
|
||||
sys.stderr.write(f"Request response code is {response.status_code} with URL {url}\n")
|
||||
sys.exit(1)
|
||||
|
||||
def getDataUser(session, url, verify):
|
||||
headers = CaseInsensitiveDict()
|
||||
headers["Accept"] = "application/json"
|
||||
headers["OCS-APIRequest"] = "true"
|
||||
response = session.get(url, headers=headers, verify=verify)
|
||||
status = response.status_code
|
||||
if (status == 200):
|
||||
jsdata = response.text
|
||||
data = json.loads(jsdata) # returns a dictionary
|
||||
return data
|
||||
else:
|
||||
sys.stderr.write(f"Request response code is {response.status_code} with URL {url}\n")
|
||||
sys.exit(1)
|
||||
|
||||
def doCmkOutput(data):
|
||||
apps_with_updates_available = {}
|
||||
str_apps_with_updates_available = ""
|
||||
print("<<<nextcloud_info:sep(59)>>>")
|
||||
print(f"NC_Version;{data['ocs']['data']['nextcloud']['system']['version']}")
|
||||
print(f"NC_Freespace;{data['ocs']['data']['nextcloud']['system']['freespace']}")
|
||||
print(f"NC_Status;{data['ocs']['meta']['status']}")
|
||||
# This update info is available only from version 28 onwards, so the key "update" does not exist in all versions before
|
||||
try:
|
||||
print(f"NC_Last_Update;{data['ocs']['data']['nextcloud']['system']['update']['lastupdatedat']}")
|
||||
print(f"NC_Update_Available;{data['ocs']['data']['nextcloud']['system']['update']['available']}")
|
||||
except KeyError:
|
||||
pass
|
||||
print(f"NC_Num_Users;{data['ocs']['data']['nextcloud']['storage']['num_users']}")
|
||||
print(f"NC_Num_Files;{data['ocs']['data']['nextcloud']['storage']['num_files']}")
|
||||
print(f"NC_Num_Shares;{data['ocs']['data']['nextcloud']['shares']['num_shares']}")
|
||||
print(f"NC_Num_Storages;{data['ocs']['data']['nextcloud']['storage']['num_storages']}")
|
||||
print(f"NC_Num_Storages_Home;{data['ocs']['data']['nextcloud']['storage']['num_storages_home']}")
|
||||
print(f"NC_Num_Storages_Local;{data['ocs']['data']['nextcloud']['storage']['num_storages_local']}")
|
||||
print(f"NC_Num_Storages_Other;{data['ocs']['data']['nextcloud']['storage']['num_storages_other']}")
|
||||
# Workaround for Nextcloud 28.0.1 (KeyError "apps")
|
||||
try:
|
||||
print(f"NC_Num_Apps_Installed;{data['ocs']['data']['nextcloud']['system']['apps']['num_installed']}")
|
||||
print(f"NC_Num_Apps_Updates_Available;{data['ocs']['data']['nextcloud']['system']['apps']['num_updates_available']}")
|
||||
apps_with_updates_available = data['ocs']['data']['nextcloud']['system']['apps']['app_updates']
|
||||
if apps_with_updates_available:
|
||||
for app, version in apps_with_updates_available.items():
|
||||
str_apps_with_updates_available = str_apps_with_updates_available + app + "/" + version + " "
|
||||
print(f"NC_Apps_With_Updates_Available;{str_apps_with_updates_available}")
|
||||
except KeyError:
|
||||
pass
|
||||
print(f"NC_Active_Users_Last_5Min;{data['ocs']['data']['activeUsers']['last5minutes']}")
|
||||
print(f"NC_Active_Users_Last_1Hour;{data['ocs']['data']['activeUsers']['last1hour']}")
|
||||
print(f"NC_Active_Users_Last_1Day;{data['ocs']['data']['activeUsers']['last24hours']}")
|
||||
print(f"NC_Webserver;{data['ocs']['data']['server']['webserver']}")
|
||||
print(f"NC_PHP_Version;{data['ocs']['data']['server']['php']['version']}")
|
||||
|
||||
print("<<<nextcloud_database:sep(59)>>>")
|
||||
print(f"NC_Database_Type;{data['ocs']['data']['server']['database']['type']}")
|
||||
print(f"NC_Database_Version;{data['ocs']['data']['server']['database']['version']}")
|
||||
print(f"NC_Database_Size;{data['ocs']['data']['server']['database']['size']}")
|
||||
# opcache entry does not exist if opcache_get_status is disabled by server settings
|
||||
# thanks to Marcus Klein from Iteratio to report (and solve!) this bug
|
||||
if (data['ocs']['data']['server']['php']['opcache']):
|
||||
print(f"NC_OPCache_Hit_Rate;{data['ocs']['data']['server']['php']['opcache']['opcache_statistics']['opcache_hit_rate']}")
|
||||
else:
|
||||
print(f"NC_OPCache_Hit_Rate;0")
|
||||
|
||||
def doCmkOutputAllUsers(session, data, verify, hostname, protocol, port, folder):
|
||||
print("<<<nextcloud_users:sep(59)>>>")
|
||||
for user in data['ocs']['data']['users']:
|
||||
nc_url = createUrlUser(user, nc_api_endpoint_user, hostname, protocol, port, folder)
|
||||
user_data = getDataUser(session, nc_url, verify)
|
||||
userid = user_data['ocs']['data']['id']
|
||||
displayname = user_data['ocs']['data']['displayname']
|
||||
lastlogin = int(user_data['ocs']['data']['lastLogin'])
|
||||
if lastlogin == 0:
|
||||
# user has never logged in
|
||||
quota_free = -1
|
||||
quota_quota = -1
|
||||
quota_relative = -1
|
||||
quota_total = -1
|
||||
quota_used = -1
|
||||
else:
|
||||
quota_free = user_data['ocs']['data']['quota']['free']
|
||||
# quota_quota == -3 --> unlimited
|
||||
quota_quota = user_data['ocs']['data']['quota']['quota']
|
||||
# quota_relative = used * 100 / (free + used)
|
||||
quota_relative = user_data['ocs']['data']['quota']['relative']
|
||||
quota_total = user_data['ocs']['data']['quota']['total']
|
||||
quota_used = user_data['ocs']['data']['quota']['used']
|
||||
print(f"{userid};{displayname};{lastlogin};{quota_free};{quota_quota};{quota_relative};{quota_total};{quota_used}")
|
||||
|
||||
def main():
|
||||
# replace password from pwd store
|
||||
cmk.utils.password_store.replace_passwords()
|
||||
getOptions()
|
||||
if (opt_hostname == ""):
|
||||
sys.stderr.write(f"No hostname given.\n")
|
||||
showUsage()
|
||||
sys.exit(1)
|
||||
if (opt_username == ""):
|
||||
sys.stderr.write(f"No username given.\n")
|
||||
showUsage()
|
||||
sys.exit(1)
|
||||
if (opt_password == ""):
|
||||
sys.stderr.write(f"No password given.\n")
|
||||
showUsage()
|
||||
sys.exit(1)
|
||||
if (opt_no_cert_check):
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
verify = False
|
||||
else:
|
||||
verify = True
|
||||
if (opt_port == ""):
|
||||
if (opt_no_https):
|
||||
protocol = "http"
|
||||
port = "80"
|
||||
else:
|
||||
protocol = "https"
|
||||
port = "443"
|
||||
else:
|
||||
if (opt_no_https):
|
||||
protocol = "http"
|
||||
else:
|
||||
protocol = "https"
|
||||
port = opt_port
|
||||
if DEBUG:
|
||||
showOptions()
|
||||
if (protocol == "http" and port == "443"):
|
||||
sys.stderr.write(f"Combining HTTP with port 443 is not supported.\n")
|
||||
sys.exit(1)
|
||||
if (protocol == "https" and port == "80"):
|
||||
sys.stderr.write(f"Combining HTTPS with port 80 is not supported.\n")
|
||||
sys.exit(1)
|
||||
pwd = opt_password
|
||||
|
||||
# create session
|
||||
session = getSession(opt_username, pwd)
|
||||
nc_url = createUrl(nc_api_endpoint, opt_hostname, protocol, port, opt_folder)
|
||||
nc_data = getData(session, nc_url, verify)
|
||||
doCmkOutput(nc_data)
|
||||
nc_url = createUrl(nc_api_endpoint_all_users, opt_hostname, protocol, port, opt_folder)
|
||||
nc_data = getDataAllUsers(session, nc_url, verify)
|
||||
doCmkOutputAllUsers(session, nc_data, verify, opt_hostname, protocol, port, opt_folder)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,16 +0,0 @@
|
||||
title: Nextcloud: Database information
|
||||
agents: linux
|
||||
catalog: unsorted
|
||||
license: GPL
|
||||
distribution: check_mk
|
||||
description:
|
||||
Works with Nextcloud version 25/26/27 (use at your own risk with lower versions).
|
||||
Tested only with mysql/mariab as underlying database.
|
||||
You may use a username/password or username/token combination to get access to the Nextcloud API.
|
||||
You can create this token within the personal settings of an administrative user in Nextcloud.
|
||||
Got to security settings and create a new app password, use this for the token.
|
||||
The user must not be secured with 2FA.
|
||||
Shows several information about a Nextcloud database (type/version/size).
|
||||
The check will raise WARN/CRIT if Database PHP OPcache hit rate is below the configurable levels.
|
||||
inventory:
|
||||
one service is created (with several details)
|
@ -1,13 +0,0 @@
|
||||
def agent_nextcloud_arguments(params, hostname, ipaddress):
|
||||
return [
|
||||
"--hostname", params["hostname"],
|
||||
"--username", params["username"],
|
||||
"--password", passwordstore_get_cmdline("%s", params["password"]),
|
||||
"--port", params["port"],
|
||||
"--folder", params["folder"],
|
||||
"--no-https", params["no_https"],
|
||||
"--no-cert-check", params["no_cert_check"],
|
||||
ipaddress,
|
||||
]
|
||||
|
||||
special_agent_info['nextcloud'] = agent_nextcloud_arguments
|
@ -1,135 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from cmk.gui.i18n import _
|
||||
from cmk.gui.plugins.metrics import (
|
||||
metric_info,
|
||||
graph_info,
|
||||
)
|
||||
|
||||
metric_info["nc_num_users"] = {
|
||||
"title": _("Number of Users"),
|
||||
"unit": "count",
|
||||
"color": "44/a",
|
||||
}
|
||||
|
||||
metric_info["nc_num_shares"] = {
|
||||
"title": _("Number of Shares"),
|
||||
"unit": "count",
|
||||
"color": "44/b",
|
||||
}
|
||||
|
||||
metric_info["nc_num_storages"] = {
|
||||
"title": _("Number of Storages"),
|
||||
"unit": "count",
|
||||
"color": "42/a",
|
||||
}
|
||||
|
||||
metric_info["nc_num_storages_home"] = {
|
||||
"title": _("Number of Home Storages"),
|
||||
"unit": "count",
|
||||
"color": "44/a",
|
||||
}
|
||||
|
||||
metric_info["nc_num_storages_local"] = {
|
||||
"title": _("Number of Local Storages"),
|
||||
"unit": "count",
|
||||
"color": "44/b",
|
||||
}
|
||||
|
||||
metric_info["nc_num_storages_other"] = {
|
||||
"title": _("Number of Other Storages"),
|
||||
"unit": "count",
|
||||
"color": "42/a",
|
||||
}
|
||||
|
||||
metric_info["nc_num_files"] = {
|
||||
"title": _("Number of Files"),
|
||||
"unit": "count",
|
||||
"color": "42/a",
|
||||
}
|
||||
|
||||
metric_info["nc_num_apps_installed"] = {
|
||||
"title": _("Number of installed Apps"),
|
||||
"unit": "count",
|
||||
"color": "43/a",
|
||||
}
|
||||
|
||||
metric_info["nc_apps_with_updates_available"] = {
|
||||
"title": _("Number of installed Apps with Updates Available"),
|
||||
"unit": "count",
|
||||
"color": "24/a",
|
||||
}
|
||||
|
||||
metric_info["nc_active_users_last_5min"] = {
|
||||
"title": _("Number of Active Users in the last 5 minutes"),
|
||||
"unit": "count",
|
||||
"color": "24/a",
|
||||
}
|
||||
|
||||
metric_info["nc_active_users_last_1hour"] = {
|
||||
"title": _("Number of Active Users in the last 1 hour"),
|
||||
"unit": "count",
|
||||
"color": "41/a",
|
||||
}
|
||||
|
||||
metric_info["nc_active_users_last_1day"] = {
|
||||
"title": _("Number of Active Users in the last 1 day"),
|
||||
"unit": "count",
|
||||
"color": "42/a",
|
||||
}
|
||||
|
||||
metric_info["nc_users_free_space"] = {
|
||||
"title": _("Free Space of User"),
|
||||
"unit": "bytes",
|
||||
"color": "22/a",
|
||||
}
|
||||
|
||||
metric_info["nc_free_space"] = {
|
||||
"title": _("Free Space on Disk"),
|
||||
"unit": "bytes",
|
||||
"color": "22/a",
|
||||
}
|
||||
|
||||
metric_info["nc_database_size"] = {
|
||||
"title": _("Database Size"),
|
||||
"unit": "bytes",
|
||||
"color": "24/a",
|
||||
}
|
||||
|
||||
metric_info["nc_database_opcache_hit_rate"] = {
|
||||
"title": _("Database PHP OPCache Hit Rate"),
|
||||
"unit": "%",
|
||||
"color": "24/a",
|
||||
}
|
||||
|
||||
metric_info["nc_users_quota_used"] = {
|
||||
"title": _("Quota used"),
|
||||
"unit": "%",
|
||||
"color": "16/a",
|
||||
}
|
||||
|
||||
graph_info["number_of_users_shares_storages_combined"] = {
|
||||
"title": _("Number of Users, Shares and Storages"),
|
||||
"metrics": [
|
||||
("nc_num_users", "area"),
|
||||
("nc_num_shares", "stack"),
|
||||
("nc_num_storages", "stack"),
|
||||
],
|
||||
}
|
||||
|
||||
graph_info["number_of_storage_types_combined"] = {
|
||||
"title": _("Number of Storage Types"),
|
||||
"metrics": [
|
||||
("nc_num_storages_home", "area"),
|
||||
("nc_num_storages_local", "stack"),
|
||||
("nc_num_storages_other", "stack"),
|
||||
],
|
||||
}
|
||||
|
||||
graph_info["number_of_active_users_combined"] = {
|
||||
"title": _("Number of Active Users"),
|
||||
"metrics": [
|
||||
("nc_active_users_last_5min", "area"),
|
||||
("nc_active_users_last_1hour", "stack"),
|
||||
("nc_active_users_last_1day", "stack"),
|
||||
],
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from cmk.gui.plugins.metrics import perfometer_info
|
||||
|
||||
perfometer_info.append({
|
||||
"type": "stacked",
|
||||
"perfometers": [
|
||||
{
|
||||
"type": "linear",
|
||||
"segments": ["nc_database_opcache_hit_rate"],
|
||||
"total": 100.0,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
perfometer_info.append({
|
||||
"type": "stacked",
|
||||
"perfometers": [
|
||||
{
|
||||
"type": "linear",
|
||||
"segments": ["nc_database_size"],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
perfometer_info.append({
|
||||
"type": "stacked",
|
||||
"perfometers": [
|
||||
{
|
||||
"type": "linear",
|
||||
"segments": ["nc_users_quota_used"],
|
||||
"total": 100.0,
|
||||
},
|
||||
],
|
||||
})
|
@ -1,43 +0,0 @@
|
||||
from cmk.gui.i18n import _
|
||||
from cmk.gui.plugins.wato import (
|
||||
CheckParameterRulespecWithoutItem,
|
||||
rulespec_registry,
|
||||
RulespecGroupCheckParametersApplications
|
||||
)
|
||||
from cmk.gui.valuespec import (
|
||||
Dictionary,
|
||||
ListChoice,
|
||||
Tuple,
|
||||
Percentage,
|
||||
Integer,
|
||||
Float,
|
||||
)
|
||||
|
||||
def _parameter_spec_nextcloud_database():
|
||||
return Dictionary(
|
||||
elements=[
|
||||
("levels_database_opcache_hit_rate", Tuple(
|
||||
title=_("Nextcloud levels for database php opcache hit rate"),
|
||||
elements=[
|
||||
Percentage(
|
||||
title=_("Warning below"),
|
||||
default_value=99.7,
|
||||
),
|
||||
Percentage(
|
||||
title=_("Critical below"),
|
||||
default_value=99.1,
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
||||
rulespec_registry.register(
|
||||
CheckParameterRulespecWithoutItem(
|
||||
check_group_name="nextcloud_database",
|
||||
group=RulespecGroupCheckParametersApplications,
|
||||
match_type="dict",
|
||||
parameter_valuespec=_parameter_spec_nextcloud_database,
|
||||
title=lambda: _("Nextcloud Database"),
|
||||
)
|
||||
)
|
@ -1,74 +0,0 @@
|
||||
from cmk.gui.i18n import _
|
||||
from cmk.gui.plugins.wato import (
|
||||
CheckParameterRulespecWithoutItem,
|
||||
rulespec_registry,
|
||||
RulespecGroupCheckParametersApplications
|
||||
)
|
||||
|
||||
from cmk.gui.valuespec import (
|
||||
Dictionary,
|
||||
ListChoice,
|
||||
Tuple,
|
||||
Percentage,
|
||||
Integer,
|
||||
Float,
|
||||
)
|
||||
|
||||
def _parameter_spec_nextcloud_info():
|
||||
return Dictionary(
|
||||
elements=[
|
||||
("levels_apps_with_updates_available", Tuple(
|
||||
title=_("Nextcloud number of installed apps with updates available"),
|
||||
elements=[
|
||||
Integer(
|
||||
title=_("Warning at"),
|
||||
default_value=1,
|
||||
),
|
||||
Integer(
|
||||
title=_("Critical at"),
|
||||
default_value=2,
|
||||
)
|
||||
],
|
||||
)),
|
||||
("levels_free_space", Tuple(
|
||||
title=_("Nextcloud levels for free disk space overall"),
|
||||
elements=[
|
||||
Float(
|
||||
title=_("Warning below"),
|
||||
default_value=8.0,
|
||||
unit="GBytes",
|
||||
),
|
||||
Float(
|
||||
title=_("Critical below"),
|
||||
default_value=4.0,
|
||||
unit="GBytes",
|
||||
)
|
||||
],
|
||||
)),
|
||||
("levels_number_of_files", Tuple(
|
||||
title=_("Nextcloud number of files"),
|
||||
elements=[
|
||||
Integer(
|
||||
title=_("Warning at"),
|
||||
default_value=100000,
|
||||
size=32,
|
||||
),
|
||||
Integer(
|
||||
title=_("Critical at"),
|
||||
default_value=250000,
|
||||
size=32,
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
||||
rulespec_registry.register(
|
||||
CheckParameterRulespecWithoutItem(
|
||||
check_group_name="nextcloud_info",
|
||||
group=RulespecGroupCheckParametersApplications,
|
||||
match_type="dict",
|
||||
parameter_valuespec=_parameter_spec_nextcloud_info,
|
||||
title=lambda: _("Nextcloud Info"),
|
||||
)
|
||||
)
|
@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from cmk.gui.i18n import _
|
||||
from cmk.gui.plugins.wato.special_agents.common import RulespecGroupDatasourceProgramsApps
|
||||
from cmk.gui.plugins.wato.utils import (
|
||||
HostRulespec,
|
||||
Rulespec,
|
||||
IndividualOrStoredPassword,
|
||||
rulespec_registry,
|
||||
)
|
||||
from cmk.gui.valuespec import (
|
||||
Dictionary,
|
||||
ListChoice,
|
||||
Checkbox,
|
||||
TextAscii,
|
||||
Password,
|
||||
)
|
||||
|
||||
def _factory_default_special_agent_nextcloud():
|
||||
return Rulespec.FACTORY_DEFAULT_UNUSED
|
||||
|
||||
def _valuespec_special_agent_nextcloud():
|
||||
return Dictionary(
|
||||
title=_("Nextcloud Server Information"),
|
||||
help = _("Checking Nextcloud servers via API"),
|
||||
elements=[
|
||||
("hostname", TextAscii(title=_("Hostname"),
|
||||
allow_empty=False,
|
||||
size = 40,
|
||||
help=_("Hostname of Nextcloud server (bare FQDN or IP), mandatory, eg. nextcloud.yourdomain.tld"))),
|
||||
("username", TextAscii(title=_("Username"),
|
||||
size = 40,
|
||||
allow_empty=False,
|
||||
help=_("Username with administrative rights, mandatory"))),
|
||||
("password", IndividualOrStoredPassword(title=_("App Password"),
|
||||
size = 40,
|
||||
allow_empty=False,
|
||||
help=_("Specify app password, mandatory, use Personal Settings|Security|Devices and Sessions within the NC UI to create one for the given user"))),
|
||||
("port", TextAscii(title=_("Port"),
|
||||
allow_empty=True,
|
||||
help=_("Specify port if not listening to HTTP(S), optional"))),
|
||||
("folder", TextAscii(title=_("Folder"),
|
||||
allow_empty=True,
|
||||
help=_("Specify subfolder if your Nextcloud instance is not installed in the web root, no trailing/leading slashes, optional"))),
|
||||
("no_https", Checkbox(title=_("Disable HTTPS"),
|
||||
help=_("Activate to disable encryption (not recommended), optional"))),
|
||||
("no_cert_check", Checkbox(title=_("Disable certificate validation"),
|
||||
help=_("Activate to disable certificate validation (not recommended), optional"))),
|
||||
],
|
||||
optional_keys=[],
|
||||
)
|
||||
|
||||
rulespec_registry.register(
|
||||
HostRulespec(
|
||||
factory_default = _factory_default_special_agent_nextcloud(),
|
||||
group = RulespecGroupDatasourceProgramsApps,
|
||||
name = "special_agents:nextcloud",
|
||||
valuespec = _valuespec_special_agent_nextcloud,
|
||||
)
|
||||
)
|
@ -1,68 +0,0 @@
|
||||
from cmk.gui.i18n import _
|
||||
from cmk.gui.plugins.wato import (
|
||||
CheckParameterRulespecWithItem,
|
||||
rulespec_registry,
|
||||
RulespecGroupCheckParametersApplications
|
||||
)
|
||||
|
||||
from cmk.gui.valuespec import (
|
||||
Dictionary,
|
||||
ListChoice,
|
||||
Tuple,
|
||||
Percentage,
|
||||
Integer,
|
||||
TextAscii,
|
||||
Float,
|
||||
)
|
||||
|
||||
def _item_spec_nextcloud_users():
|
||||
return TextAscii(
|
||||
title=_("User ID")
|
||||
)
|
||||
|
||||
def _parameter_spec_nextcloud_users():
|
||||
return Dictionary(
|
||||
elements=[
|
||||
("levels_users_quota_used", Tuple(
|
||||
title=_("Nextcloud levels for quota usage of users"),
|
||||
elements=[
|
||||
Percentage(
|
||||
title=_("Warning at"),
|
||||
default_value=65.0,
|
||||
unit="%",
|
||||
),
|
||||
Percentage(
|
||||
title=_("Critical at"),
|
||||
default_value=85.0,
|
||||
unit="%",
|
||||
)
|
||||
],
|
||||
)),
|
||||
("levels_users_free_space", Tuple(
|
||||
title=_("Nextcloud levels for free disk space of users"),
|
||||
elements=[
|
||||
Float(
|
||||
title=_("Warning below"),
|
||||
default_value=256.0,
|
||||
unit="MBytes",
|
||||
),
|
||||
Float(
|
||||
title=_("Critical below"),
|
||||
default_value=128.0,
|
||||
unit="MBytes",
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
||||
rulespec_registry.register(
|
||||
CheckParameterRulespecWithItem(
|
||||
check_group_name="nextcloud_users",
|
||||
group=RulespecGroupCheckParametersApplications,
|
||||
match_type="dict",
|
||||
item_spec=_item_spec_nextcloud_users,
|
||||
parameter_valuespec=_parameter_spec_nextcloud_users,
|
||||
title=lambda: _("Nextcloud Users"),
|
||||
)
|
||||
)
|
BIN
mkp/.DS_Store
vendored
Normal file
BIN
mkp/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
mkp/Nextcloud-3.1.1.mkp
Normal file
BIN
mkp/Nextcloud-3.1.1.mkp
Normal file
Binary file not shown.
105
nextcloud/agent_based/nextcloud_database.py
Normal file
105
nextcloud/agent_based/nextcloud_database.py
Normal file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||
# pylint: disable=line-too-long
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import NotRequired, TypedDict
|
||||
|
||||
from cmk.agent_based.v2 import (
|
||||
AgentSection,
|
||||
CheckPlugin,
|
||||
CheckResult,
|
||||
Metric,
|
||||
render,
|
||||
Result,
|
||||
Service,
|
||||
State,
|
||||
StringTable,
|
||||
DiscoveryResult,
|
||||
)
|
||||
|
||||
|
||||
class _ItemData(TypedDict):
|
||||
dbtype: NotRequired[str]
|
||||
version: NotRequired[str]
|
||||
size: NotRequired[int]
|
||||
opcache_hit_rate: NotRequired[float]
|
||||
|
||||
|
||||
Section = Mapping[str, _ItemData]
|
||||
|
||||
|
||||
def get_state_lower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
if value < warn:
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
|
||||
def discover_nextcloud_database(section) -> DiscoveryResult:
|
||||
yield Service()
|
||||
|
||||
|
||||
def check_nextcloud_database(params, section) -> CheckResult:
|
||||
for key in section:
|
||||
if key == "database":
|
||||
opcache_hit_rate = section[key]["opcache_hit_rate"]
|
||||
size = section[key]["size"]
|
||||
dbtype = section[key]["dbtype"]
|
||||
version = section[key]["version"]
|
||||
_level_type, levels = params["levels_database_opcache_hit_rate"]
|
||||
# create graph for opcache hit rate
|
||||
yield Metric(
|
||||
"nc_database_opcache_hit_rate", opcache_hit_rate, levels=levels
|
||||
)
|
||||
# create graph for database size
|
||||
yield Metric("nc_database_size", size)
|
||||
state = get_state_lower(levels, opcache_hit_rate)
|
||||
summary = f"PHP OPCache hit rate: {render.percent(opcache_hit_rate)}"
|
||||
if opcache_hit_rate == 0:
|
||||
state = State.UNKNOWN
|
||||
summary = "PHP OPCache hit rate: 0% - please check if opcache_get_status is enabled"
|
||||
details = f"\nDatabase type: {dbtype}\nDatabase version: {version}\nDatabase size: {render.bytes(size)}"
|
||||
yield Result(state=state, summary=summary, details=details)
|
||||
|
||||
|
||||
def parse_nextcloud_database(string_table: StringTable) -> Section:
|
||||
parsed_data = {"database": {}}
|
||||
params_list = [
|
||||
"NC_Database_Type",
|
||||
"NC_Database_Version",
|
||||
"NC_Database_Size",
|
||||
"NC_OPCache_Hit_Rate",
|
||||
]
|
||||
for line in string_table:
|
||||
if line[0] in params_list:
|
||||
param = line[0]
|
||||
value = line[1]
|
||||
if param == "NC_Database_Type":
|
||||
parsed_data["database"]["dbtype"] = value
|
||||
elif param == "NC_Database_Version":
|
||||
parsed_data["database"]["version"] = value
|
||||
elif param == "NC_Database_Size":
|
||||
parsed_data["database"]["size"] = int(value)
|
||||
elif param == "NC_OPCache_Hit_Rate":
|
||||
parsed_data["database"]["opcache_hit_rate"] = float(value)
|
||||
return parsed_data
|
||||
|
||||
|
||||
agent_section_nextcloud_database = AgentSection(
|
||||
name="nextcloud_database",
|
||||
parse_function=parse_nextcloud_database,
|
||||
)
|
||||
|
||||
check_plugin_nextcloud_database = CheckPlugin(
|
||||
name="nextcloud_database",
|
||||
service_name="Nextcloud Database",
|
||||
discovery_function=discover_nextcloud_database,
|
||||
check_function=check_nextcloud_database,
|
||||
check_default_parameters={
|
||||
"levels_database_opcache_hit_rate": ("fixed", (95.0, 85.0)),
|
||||
},
|
||||
check_ruleset_name="nextcloud_database",
|
||||
)
|
@ -1,10 +1,24 @@
|
||||
#!/usr/bin/env python3
|
||||
from pprint import pprint
|
||||
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||
# pylint: disable=line-too-long, too-many-branches, too-many-locals, too-many-statements
|
||||
|
||||
from datetime import datetime
|
||||
from .agent_based_api.v1 import register, render, Service, Result, State, Metric
|
||||
|
||||
from cmk.agent_based.v2 import (
|
||||
AgentSection,
|
||||
CheckPlugin,
|
||||
CheckResult,
|
||||
Metric,
|
||||
render,
|
||||
Result,
|
||||
Service,
|
||||
State,
|
||||
StringTable,
|
||||
DiscoveryResult,
|
||||
)
|
||||
|
||||
|
||||
def getStateUpper(levels, value):
|
||||
def get_state_upper(levels, value):
|
||||
warn, crit = levels
|
||||
if value >= crit:
|
||||
return State.CRIT
|
||||
@ -13,7 +27,7 @@ def getStateUpper(levels, value):
|
||||
return State.OK
|
||||
|
||||
|
||||
def getStateLower(levels, value):
|
||||
def get_state_lower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
@ -22,22 +36,24 @@ def getStateLower(levels, value):
|
||||
return State.OK
|
||||
|
||||
|
||||
def discover_nextcloud_info(section):
|
||||
yield(Service())
|
||||
def discover_nextcloud_info(section) -> DiscoveryResult:
|
||||
yield Service()
|
||||
|
||||
|
||||
def check_nextcloud_info(params, section):
|
||||
def check_nextcloud_info(params, section) -> CheckResult:
|
||||
for key in section:
|
||||
if key == "nextcloud":
|
||||
levels_free_space = params["levels_free_space"]
|
||||
levels_number_of_files = params["levels_number_of_files"]
|
||||
_level_type, levels_free_space = params["levels_free_space"]
|
||||
_level_type, levels_number_of_files = params["levels_number_of_files"]
|
||||
# update infos are available only from Nextcloud version 28 onwards
|
||||
try:
|
||||
last_update = section[key]["last_update"]
|
||||
update_available = section[key]["update_available"]
|
||||
last_update_human = datetime.fromtimestamp(last_update)
|
||||
except KeyError:
|
||||
last_update = "Update information not available, update to at least version 28"
|
||||
last_update = (
|
||||
"Update information not available, update to at least version 28"
|
||||
)
|
||||
update_available = "False"
|
||||
last_update_human = "Information not available"
|
||||
status = section[key]["status"]
|
||||
@ -46,14 +62,14 @@ def check_nextcloud_info(params, section):
|
||||
php_version = section[key]["php_version"]
|
||||
webserver = section[key]["webserver"]
|
||||
num_files = section[key]["number_files"]
|
||||
num_shares = section[key]["number_shares"]
|
||||
num_shares = section[key]["number_shares"]
|
||||
|
||||
# create graph for number of files and shares
|
||||
yield(Metric("nc_num_files", num_files))
|
||||
yield(Metric("nc_num_shares", num_shares))
|
||||
yield Metric("nc_num_files", num_files)
|
||||
yield Metric("nc_num_shares", num_shares)
|
||||
|
||||
# create overall result
|
||||
summary = f"Status is {status}, Last update: {last_update_human}"
|
||||
summary = f"Status is {status}, Last update check: {last_update_human}"
|
||||
details = f"Nextcloud version: {version}\nPHP version: {php_version}\nWebserver: {webserver}\n\nNumber of files: {num_files}\nNumber of shares: {num_shares}\n\nFree space on disk: {render.bytes(free_space)}\n"
|
||||
if status == "ok":
|
||||
state = State.OK
|
||||
@ -64,31 +80,31 @@ def check_nextcloud_info(params, section):
|
||||
# Create result for available updates
|
||||
if update_available != "False":
|
||||
state = State.WARN
|
||||
notice = f"Update is available"
|
||||
notice = "Update is available"
|
||||
else:
|
||||
state = State.OK
|
||||
notice = "No update available"
|
||||
if state != State.OK:
|
||||
yield(Result(state=state, notice=notice))
|
||||
yield Result(state=state, notice=notice)
|
||||
|
||||
# Create result for free space on disk
|
||||
# Levels for free space are given in GBytes, we have to adjust this here
|
||||
warn, crit = levels_free_space
|
||||
warn = warn*1024*1024*1024
|
||||
crit = crit*1024*1024*1024
|
||||
state = getStateLower((warn, crit), free_space)
|
||||
warn = warn * 1024 * 1024 * 1024
|
||||
crit = crit * 1024 * 1024 * 1024
|
||||
state = get_state_lower((warn, crit), free_space)
|
||||
# create graph for free space on disk
|
||||
yield(Metric("nc_free_space", free_space, levels=(warn,crit)))
|
||||
yield Metric("nc_free_space", free_space, levels=(warn, crit))
|
||||
notice = f"Remaining free space on disk: {render.bytes(free_space)}"
|
||||
if state != State.OK:
|
||||
yield(Result(state=state, notice=notice))
|
||||
yield Result(state=state, notice=notice)
|
||||
|
||||
# Create result for number of files
|
||||
warn, crit = levels_number_of_files
|
||||
state = getStateUpper((warn, crit), num_files)
|
||||
state = get_state_upper((warn, crit), num_files)
|
||||
notice = f"Number of files: {num_files}"
|
||||
if state != State.OK:
|
||||
yield(Result(state=state, notice=notice))
|
||||
yield Result(state=state, notice=notice)
|
||||
elif key == "users":
|
||||
num_users = section[key]["number"]
|
||||
num_active_last1hour = section[key]["active_last1hour"]
|
||||
@ -100,7 +116,7 @@ def check_nextcloud_info(params, section):
|
||||
yield Metric("nc_active_users_last_1day", num_active_last1day)
|
||||
yield Metric("nc_active_users_last_5min", num_active_last5min)
|
||||
notice = f"Number of users: {num_users}\n\nActive users last 5 min: {num_active_last5min}\nActive user since last hour: {num_active_last1hour}\nActive users since last day: {num_active_last1day}"
|
||||
yield(Result(state=State.OK, notice=notice))
|
||||
yield Result(state=State.OK, notice=notice)
|
||||
elif key == "storages":
|
||||
num_storages = section[key]["number"]
|
||||
num_storages_home = section[key]["number_home"]
|
||||
@ -112,7 +128,7 @@ def check_nextcloud_info(params, section):
|
||||
yield Metric("nc_num_storages_local", num_storages_local)
|
||||
yield Metric("nc_num_storages_other", num_storages_other)
|
||||
notice = f"Number of storages: {num_storages}\nNumber of home/local/other storages: {num_storages_home}/{num_storages_local}/{num_storages_other}"
|
||||
yield(Result(state=State.OK, notice=notice))
|
||||
yield Result(state=State.OK, notice=notice)
|
||||
elif key == "apps":
|
||||
# Workaround for Nextcloud 28, "apps" info is not always available
|
||||
try:
|
||||
@ -123,25 +139,30 @@ def check_nextcloud_info(params, section):
|
||||
else:
|
||||
app_versions = ""
|
||||
# create graphs for number of apps
|
||||
levels = params["levels_apps_with_updates_available"]
|
||||
_level_type, levels = params["levels_apps_with_updates_available"]
|
||||
yield Metric("nc_num_apps_installed", num_apps_installed)
|
||||
yield Metric("nc_apps_with_updates_available", num_apps_with_updates_available, levels=levels)
|
||||
state = getStateUpper(levels, num_apps_with_updates_available)
|
||||
if (app_versions == ""):
|
||||
yield Metric(
|
||||
"nc_apps_with_updates_available",
|
||||
num_apps_with_updates_available,
|
||||
levels=levels,
|
||||
)
|
||||
state = get_state_upper(levels, num_apps_with_updates_available)
|
||||
if app_versions == "":
|
||||
notice = f"Number of installed apps: {num_apps_installed}\nNumber of apps with updates available: {num_apps_with_updates_available}"
|
||||
else:
|
||||
notice = f"Number of installed apps: {num_apps_installed}\nNumber of apps with updates available: {num_apps_with_updates_available}\nNew app versions available: {app_versions}"
|
||||
yield(Result(state=state, notice=notice))
|
||||
yield Result(state=state, notice=notice)
|
||||
except KeyError:
|
||||
# TBD
|
||||
pass
|
||||
|
||||
|
||||
def parse_nextcloud_info_section(string_table):
|
||||
def parse_nextcloud_info(string_table: StringTable) -> dict:
|
||||
parsed_data = {
|
||||
"nextcloud" : {},
|
||||
"storages" : {},
|
||||
"apps" : {},
|
||||
"users" : {},
|
||||
"nextcloud": {},
|
||||
"storages": {},
|
||||
"apps": {},
|
||||
"users": {},
|
||||
}
|
||||
params_list = [
|
||||
"NC_Version",
|
||||
@ -163,7 +184,7 @@ def parse_nextcloud_info_section(string_table):
|
||||
"NC_Apps_With_Updates_Available",
|
||||
"NC_Active_Users_Last_5Min",
|
||||
"NC_Active_Users_Last_1Hour",
|
||||
"NC_Active_Users_Last_1Day"
|
||||
"NC_Active_Users_Last_1Day",
|
||||
]
|
||||
for line in string_table:
|
||||
if line[0] in params_list:
|
||||
@ -209,25 +230,23 @@ def parse_nextcloud_info_section(string_table):
|
||||
parsed_data["users"]["active_last1hour"] = int(value)
|
||||
elif param == "NC_Active_Users_Last_1Day":
|
||||
parsed_data["users"]["active_last1day"] = int(value)
|
||||
#pprint(parsed_data)
|
||||
return parsed_data
|
||||
|
||||
|
||||
register.agent_section(
|
||||
agent_section_nextcloud_info = AgentSection(
|
||||
name="nextcloud_info",
|
||||
parse_function=parse_nextcloud_info_section,
|
||||
parse_function=parse_nextcloud_info,
|
||||
)
|
||||
|
||||
|
||||
register.check_plugin(
|
||||
check_plugin_nextcloud_info = CheckPlugin(
|
||||
name="nextcloud_info",
|
||||
service_name="Nextcloud Info",
|
||||
discovery_function=discover_nextcloud_info,
|
||||
check_function=check_nextcloud_info,
|
||||
check_default_parameters={
|
||||
"levels_apps_with_updates_available": (1, 2),
|
||||
"levels_free_space": (8.0, 4.0),
|
||||
"levels_number_of_files": (100000, 250000),
|
||||
"levels_apps_with_updates_available": ("fixed", (1, 2)),
|
||||
"levels_free_space": ("fixed", (8.0, 4.0)),
|
||||
"levels_number_of_files": ("fixed", (100_000, 250_000)),
|
||||
},
|
||||
check_ruleset_name="nextcloud_info",
|
||||
)
|
||||
)
|
@ -1,9 +1,24 @@
|
||||
#!/usr/bin/env python3
|
||||
from pprint import pprint
|
||||
from time import time
|
||||
from .agent_based_api.v1 import register, render, Service, Result, State, Metric
|
||||
# pylint: disable=missing-module-docstring, unused-argument, missing-function-docstring
|
||||
# pylint: disable=line-too-long, too-many-locals
|
||||
|
||||
def getStateUpper(levels, value):
|
||||
from time import time
|
||||
|
||||
from cmk.agent_based.v2 import (
|
||||
AgentSection,
|
||||
CheckPlugin,
|
||||
CheckResult,
|
||||
Metric,
|
||||
render,
|
||||
Result,
|
||||
Service,
|
||||
State,
|
||||
StringTable,
|
||||
DiscoveryResult,
|
||||
)
|
||||
|
||||
|
||||
def get_state_upper(levels, value):
|
||||
warn, crit = levels
|
||||
if value >= crit:
|
||||
return State.CRIT
|
||||
@ -11,7 +26,8 @@ def getStateUpper(levels, value):
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
def getStateLower(levels, value):
|
||||
|
||||
def get_state_lower(levels, value):
|
||||
warn, crit = levels
|
||||
if value < crit:
|
||||
return State.CRIT
|
||||
@ -19,11 +35,13 @@ def getStateLower(levels, value):
|
||||
return State.WARN
|
||||
return State.OK
|
||||
|
||||
def discover_nextcloud_users(section):
|
||||
for key in section:
|
||||
yield(Service(item = key))
|
||||
|
||||
def check_nextcloud_users(item, params, section):
|
||||
def discover_nextcloud_users(section) -> DiscoveryResult:
|
||||
for key in section:
|
||||
yield Service(item=key)
|
||||
|
||||
|
||||
def check_nextcloud_users(item, params, section) -> CheckResult:
|
||||
userid = item
|
||||
quota_used_percent = section[item][0]
|
||||
quota_used_bytes = section[item][1]
|
||||
@ -32,30 +50,33 @@ def check_nextcloud_users(item, params, section):
|
||||
last_login_human = section[item][4]
|
||||
last_login_since = section[item][5]
|
||||
free_space = quota_total_bytes - quota_used_bytes
|
||||
#print(free_space)
|
||||
levels_quota_used = params["levels_users_quota_used"]
|
||||
levels_free_space = params["levels_users_free_space"]
|
||||
# print(free_space)
|
||||
_level_type, levels_quota_used = params["levels_users_quota_used"]
|
||||
_level_type, levels_free_space = params["levels_users_free_space"]
|
||||
if last_login_human == "never":
|
||||
quota_used_percent = 0
|
||||
details = f"User ID is '{userid}', Last login: {last_login_human}"
|
||||
summary = f"Used quota of '{display_name}' can't be calculated yet (never logged in)"
|
||||
summary = (
|
||||
f"Used quota of '{display_name}' can't be calculated yet (never logged in)"
|
||||
)
|
||||
else:
|
||||
# Levels are given in MBytes, we have to adjust this here
|
||||
warn, crit = levels_free_space
|
||||
warn = warn*1024*1024
|
||||
crit = crit*1024*1024
|
||||
state = getStateLower((warn, crit), free_space)
|
||||
warn = warn * 1024 * 1024
|
||||
crit = crit * 1024 * 1024
|
||||
state = get_state_lower((warn, crit), free_space)
|
||||
details = f"User ID is '{userid}'\nLast login: {last_login_human} ({last_login_since} ago)\nFree space: {render.bytes(free_space)}"
|
||||
summary = f"Used quota of '{display_name}' is {render.percent(quota_used_percent)}, {render.bytes(quota_used_bytes)}/{render.bytes(quota_total_bytes)} used"
|
||||
notice = f"Remaining free space: {render.bytes(free_space)}"
|
||||
yield Metric("nc_users_free_space", free_space, levels=(warn, crit))
|
||||
if state != State.OK:
|
||||
yield(Result(state=state, notice=notice))
|
||||
yield Result(state=state, notice=notice)
|
||||
yield Metric("nc_users_quota_used", quota_used_percent, levels=levels_quota_used)
|
||||
state = getStateUpper(levels_quota_used, quota_used_percent)
|
||||
yield(Result(state=state, summary=summary, details=details))
|
||||
state = get_state_upper(levels_quota_used, quota_used_percent)
|
||||
yield Result(state=state, summary=summary, details=details)
|
||||
|
||||
def parse_nextcloud_users_section(string_table):
|
||||
|
||||
def parse_nextcloud_users(string_table: StringTable) -> dict:
|
||||
# Raw output from check:
|
||||
# userid;displayname;lastLogin;quota_free;quota_quota;quota_relative;quota_total;quota_used
|
||||
# str;str;int(milli seconds since epoch);int(bytes);int(bytes);float(percent);int(bytes);int(bytes)
|
||||
@ -63,7 +84,7 @@ def parse_nextcloud_users_section(string_table):
|
||||
for line in string_table:
|
||||
userid = line[0]
|
||||
display_name = line[1]
|
||||
last_login = int(line[2])/1000
|
||||
last_login = int(line[2]) / 1000
|
||||
if last_login == 0:
|
||||
# user never logged in
|
||||
last_login_human = "never"
|
||||
@ -74,25 +95,37 @@ def parse_nextcloud_users_section(string_table):
|
||||
login_diff = curr_time - last_login
|
||||
last_login_human = render.datetime(last_login)
|
||||
last_login_since = render.timespan(login_diff)
|
||||
quota_quota = int(line[4])
|
||||
if quota_quota == -3:
|
||||
# TBD, no quota set for user
|
||||
pass
|
||||
quota_relative = float(line[5])
|
||||
quota_total = float(line[6])
|
||||
quota_used = float(line[7])
|
||||
parsed_data[f"{userid}"] = [quota_relative, quota_used, quota_total, display_name, last_login_human, last_login_since]
|
||||
parsed_data[f"{userid}"] = [
|
||||
quota_relative,
|
||||
quota_used,
|
||||
quota_total,
|
||||
display_name,
|
||||
last_login_human,
|
||||
last_login_since,
|
||||
]
|
||||
return parsed_data
|
||||
|
||||
register.agent_section(
|
||||
name = "nextcloud_users",
|
||||
parse_function = parse_nextcloud_users_section,
|
||||
|
||||
|
||||
agent_section_nextcloud_users = AgentSection(
|
||||
name="nextcloud_users",
|
||||
parse_function=parse_nextcloud_users,
|
||||
)
|
||||
|
||||
register.check_plugin(
|
||||
name = "nextcloud_users",
|
||||
service_name = "Nextcloud User %s",
|
||||
discovery_function = discover_nextcloud_users,
|
||||
check_function = check_nextcloud_users,
|
||||
check_default_parameters = {
|
||||
"levels_users_quota_used": (65.0, 85.00),
|
||||
"levels_users_free_space": (256.0, 128.0)
|
||||
check_plugin_nextcloud_users = CheckPlugin(
|
||||
name="nextcloud_users",
|
||||
service_name="Nextcloud User %s",
|
||||
discovery_function=discover_nextcloud_users,
|
||||
check_function=check_nextcloud_users,
|
||||
check_default_parameters={
|
||||
"levels_users_quota_used": ("fixed", (65.0, 85.0)),
|
||||
"levels_users_free_space": ("fixed", (256.0, 128.0)),
|
||||
},
|
||||
check_ruleset_name="nextcloud_users",
|
||||
)
|
16
nextcloud/checkman/nextcloud_database
Normal file
16
nextcloud/checkman/nextcloud_database
Normal file
@ -0,0 +1,16 @@
|
||||
title: Nextcloud: Database information
|
||||
agents: linux
|
||||
catalog: unsorted
|
||||
license: GPL
|
||||
distribution: check_mk
|
||||
description:
|
||||
Works with Nextcloud version 25/26/27/28/29/30 (use at your own risk with lower versions).
|
||||
Tested only with mariab as underlying database.
|
||||
You have to use a username/app password combination to get access to the Nextcloud API.
|
||||
You can create this app password within the personal settings of an administrative user in Nextcloud.
|
||||
Got to security settings and create a new app password.
|
||||
The user must not be secured with 2FA.
|
||||
Shows several information about a Nextcloud database (type/version/size).
|
||||
The check will raise WARN/CRIT if Database PHP OPcache hit rate is below the configurable levels.
|
||||
inventory:
|
||||
one service is created (with several details)
|
@ -4,15 +4,15 @@ catalog: unsorted
|
||||
license: GPL
|
||||
distribution: check_mk
|
||||
description:
|
||||
Works with Nextcloud version 25/26/27 (use at your own risk with lower versions).
|
||||
Tested only with mysql/mariab as underlying database.
|
||||
You may use a username/password or username/token combination to get access to the Nextcloud API.
|
||||
You can create this token within the personal settings of an administrative user in Nextcloud.
|
||||
Got to security settings and create a new app password, use this for the token.
|
||||
Works with Nextcloud version 25/26/27/28/29/30 (use at your own risk with lower versions).
|
||||
Tested only with mariab as underlying database.
|
||||
You have to use a username/app password combination to get access to the Nextcloud API.
|
||||
You can create this app password within the personal settings of an administrative user in Nextcloud.
|
||||
Got to security settings and create a new app password.
|
||||
The user must not be secured with 2FA.
|
||||
Shows several information about a Nextcloud instance, e.g. number of files/storages/(active)users, free space on disk.
|
||||
The check will raise CRIT if the Nextcloud instance is not in "ok" state.
|
||||
The check will raise WARN if there is an update availbale for Nextcloud.
|
||||
The check will raise WARN if there is an update available for Nextcloud.
|
||||
The check will raise WARN/CRIT if free space on disk is below the configurable levels.
|
||||
The check will raise WARN/CRIT if the number of installed apps with available updates is above the configurable levels.
|
||||
The check will raise WARN/CRIT if the number of files is above the configurable levels.
|
@ -4,10 +4,11 @@ catalog: unsorted
|
||||
license: GPL
|
||||
distribution: check_mk
|
||||
description:
|
||||
Works with Nextcloud version 25/26/27 (use at your own risk with lower versions).
|
||||
You may use a username/password or username/token combination to get access to the Nextcloud API.
|
||||
You can create this token within the personal settings of an administrative user in Nextcloud.
|
||||
Got to security settings and create a new app password, use this for the token.
|
||||
Works with Nextcloud version 25/26/27/28/29/30 (use at your own risk with lower versions).
|
||||
Tested only with mariab as underlying database.
|
||||
You have to use a username/app password combination to get access to the Nextcloud API.
|
||||
You can create this app password within the personal settings of an administrative user in Nextcloud.
|
||||
Got to security settings and create a new app password.
|
||||
The user must not be secured with 2FA.
|
||||
Shows the usage of storage quota used by each user in percent of the maximum allowed quota.
|
||||
Shows the remaining free space for each user based on his/her max quota and used space.
|
198
nextcloud/graphing/graph_nextcloud.py
Normal file
198
nextcloud/graphing/graph_nextcloud.py
Normal file
@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env python3
|
||||
"""graphing and metrics definitions"""
|
||||
|
||||
from cmk.graphing.v1 import Title
|
||||
from cmk.graphing.v1.graphs import Graph, MinimalRange
|
||||
from cmk.graphing.v1.metrics import Color, DecimalNotation, SINotation, Metric, Unit
|
||||
from cmk.graphing.v1.perfometers import Open, Closed, FocusRange, Perfometer, Stacked
|
||||
|
||||
|
||||
metric_nc_num_users = Metric(
|
||||
name="nc_num_users",
|
||||
title=Title("Number of Users"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.PURPLE,
|
||||
)
|
||||
|
||||
metric_nc_num_shares = Metric(
|
||||
name="nc_num_shares",
|
||||
title=Title("Number of Shares"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.BROWN,
|
||||
)
|
||||
|
||||
metric_nc_num_storages = Metric(
|
||||
name="nc_num_storages",
|
||||
title=Title("Number of Storages"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.BLUE,
|
||||
)
|
||||
|
||||
metric_nc_num_storages_home = Metric(
|
||||
name="nc_num_storages_home",
|
||||
title=Title("Number of Home Storages"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.GREEN,
|
||||
)
|
||||
|
||||
metric_nc_num_storages_local = Metric(
|
||||
name="nc_num_storages_local",
|
||||
title=Title("Number of Local Storages"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.DARK_GREEN,
|
||||
)
|
||||
|
||||
|
||||
metric_nc_num_storages_other = Metric(
|
||||
name="nc_num_storages_other",
|
||||
title=Title("Number of Other Storages"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.LIGHT_GREEN,
|
||||
)
|
||||
|
||||
metric_nc_num_files = Metric(
|
||||
name="nc_num_files",
|
||||
title=Title("Number of Files"),
|
||||
unit=Unit(SINotation("")),
|
||||
color=Color.RED,
|
||||
)
|
||||
|
||||
metric_nc_num_apps_installed = Metric(
|
||||
name="nc_num_apps_installed",
|
||||
title=Title("Number of installed Apps"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.GREEN,
|
||||
)
|
||||
|
||||
metric_nc_apps_with_updates_available = Metric(
|
||||
name="nc_apps_with_updates_available",
|
||||
title=Title("Number of installed Apps with Updates Available"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.RED,
|
||||
)
|
||||
|
||||
metric_nc_active_users_last_5min = Metric(
|
||||
name="nc_active_users_last_5min",
|
||||
title=Title("Number of Active Users in the last 5 minutes"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.LIGHT_RED,
|
||||
)
|
||||
|
||||
metric_nc_active_users_last_1hour = Metric(
|
||||
name="nc_active_users_last_1hour",
|
||||
title=Title("Number of Active Users in the last 1 hour"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.LIGHT_GREEN,
|
||||
)
|
||||
|
||||
metric_nc_active_users_last_1day = Metric(
|
||||
name="nc_active_users_last_1day",
|
||||
title=Title("Number of Active Users in the last 1 day"),
|
||||
unit=Unit(DecimalNotation("")),
|
||||
color=Color.LIGHT_BLUE,
|
||||
)
|
||||
|
||||
metric_nc_users_free_space = Metric(
|
||||
name="nc_users_free_space",
|
||||
title=Title("Free Space of User"),
|
||||
unit=Unit(SINotation("bytes")),
|
||||
color=Color.LIGHT_BLUE,
|
||||
)
|
||||
|
||||
metric_nc_free_space = Metric(
|
||||
name="nc_free_space",
|
||||
title=Title("Free Space on Disk"),
|
||||
unit=Unit(SINotation("bytes")),
|
||||
color=Color.DARK_BLUE,
|
||||
)
|
||||
|
||||
metric_nc_database_size = Metric(
|
||||
name="nc_database_size",
|
||||
title=Title("Database Size"),
|
||||
unit=Unit(SINotation("bytes")),
|
||||
color=Color.GREEN,
|
||||
)
|
||||
|
||||
metric_nc_database_opcache_hit_rate = Metric(
|
||||
name="nc_database_opcache_hit_rate",
|
||||
title=Title("Database PHP OPCache Hit Rate"),
|
||||
unit=Unit(DecimalNotation("%")),
|
||||
color=Color.LIGHT_BLUE,
|
||||
)
|
||||
|
||||
|
||||
metric_nc_users_quota_used = Metric(
|
||||
name="nc_users_quota_used",
|
||||
title=Title("Quota used"),
|
||||
unit=Unit(DecimalNotation("%")),
|
||||
color=Color.BLUE,
|
||||
)
|
||||
|
||||
|
||||
graph_nc_number_of_users_shares_storages = Graph(
|
||||
name="number_of_users_shares_storages_combined",
|
||||
title=Title("Number of Users, Shares and Storages"),
|
||||
# names here refer to the metric names above
|
||||
simple_lines=["nc_num_users", "nc_num_shares", "nc_num_storages"],
|
||||
minimal_range=MinimalRange(0, 200),
|
||||
)
|
||||
|
||||
graph_nc_number_of_storage_types = Graph(
|
||||
name="number_of_storage_types_combined",
|
||||
title=Title("Number of Storage Types"),
|
||||
# names here refer to the metric names above
|
||||
simple_lines=[
|
||||
"nc_num_storages_home",
|
||||
"nc_num_storages_local",
|
||||
"nc_num_storages_other",
|
||||
],
|
||||
minimal_range=MinimalRange(0, 100),
|
||||
)
|
||||
|
||||
graph_nc_number_of_active_users = Graph(
|
||||
name="number_of_active_users_combined",
|
||||
title=Title("Number of Active Users"),
|
||||
# names here refer to the metric names above
|
||||
simple_lines=[
|
||||
"nc_active_users_last_5min",
|
||||
"nc_active_users_last_1hour",
|
||||
"nc_active_users_last_1day",
|
||||
],
|
||||
minimal_range=MinimalRange(0, 100),
|
||||
)
|
||||
|
||||
|
||||
perfometer_nc_database_op_cache_hit_rate = Perfometer(
|
||||
name="nc_database_opcache_hit_rate",
|
||||
focus_range=FocusRange(
|
||||
Closed(0),
|
||||
Closed(100),
|
||||
),
|
||||
segments=("nc_database_opcache_hit_rate",),
|
||||
)
|
||||
|
||||
perfometer_nc_database_size = Perfometer(
|
||||
name="nc_database_size",
|
||||
focus_range=FocusRange(Open(0.0), Open(500.0)),
|
||||
segments=["nc_database_size"],
|
||||
)
|
||||
|
||||
perfometer_nc_quota_used = Perfometer(
|
||||
name="nc_users_quota_used",
|
||||
focus_range=FocusRange(Closed(0), Closed(100)),
|
||||
segments=["nc_users_quota_used"],
|
||||
)
|
||||
|
||||
perfometer_nc_info = Stacked(
|
||||
name="nc_info",
|
||||
lower=Perfometer(
|
||||
name="nc_num_users",
|
||||
focus_range=FocusRange(Closed(0), Open(200)),
|
||||
segments=["nc_num_users"],
|
||||
),
|
||||
upper=Perfometer(
|
||||
name="nc_num_apps_installed",
|
||||
focus_range=FocusRange(Closed(0), Open(100)),
|
||||
segments=["nc_num_apps_installed"],
|
||||
),
|
||||
)
|
312
nextcloud/libexec/agent_nextcloud
Executable file
312
nextcloud/libexec/agent_nextcloud
Executable file
@ -0,0 +1,312 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=missing-module-docstring, missing-class-docstring, missing-function-docstring
|
||||
# pylint: disable=too-many-branches, line-too-long, too-many-statements
|
||||
# pylint: disable=too-many-arguments, too-many-positional-arguments, too-many-locals
|
||||
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
import requests
|
||||
import urllib3
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
|
||||
NC_API_ENDPOINT = "ocs/v2.php/apps/serverinfo/api/v1/info?format=json"
|
||||
NC_API_ENDPOINT_ALL_USERS = "ocs/v1.php/cloud/users?format=json"
|
||||
NC_API_ENDPOINT_USER = "ocs/v1.php/cloud/users"
|
||||
|
||||
|
||||
def get_args() -> argparse.Namespace:
|
||||
parser: argparse.ArgumentParser = argparse.ArgumentParser(
|
||||
description="Nextcloud server parameters"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--hostname", required=True, type=str, help="Hostname or IP of nextcloud server"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--username", required=True, type=str, help="User with admin privileges"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--password", required=True, type=str, help="App password for the user"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--port",
|
||||
required=False,
|
||||
type=int,
|
||||
help="Port where the server is listening on (if not HTTP/HTTPS)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--folder",
|
||||
required=False,
|
||||
type=str,
|
||||
help="Folder if not installed in web root directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-https",
|
||||
required=False,
|
||||
default=False,
|
||||
help="Disable HTTPS",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-cert-check",
|
||||
required=False,
|
||||
default=False,
|
||||
help="Disable certificate checks",
|
||||
action="store_true",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def create_url(endpoint, hostname, protocol, port, folder):
|
||||
# these parameters are needed, otherwise no information about updates regarding apps and Nextcloud itself are reported (since version 28)
|
||||
params = "skipApps=false&skipUpdate=false"
|
||||
if folder == "":
|
||||
url = f"{protocol}://{hostname}:{port}/{endpoint}"
|
||||
else:
|
||||
url = f"{protocol}://{hostname}:{port}/{folder}/{endpoint}"
|
||||
if endpoint == NC_API_ENDPOINT:
|
||||
url = f"{url}&{params}"
|
||||
return url
|
||||
|
||||
|
||||
def create_url_user(user, endpoint, hostname, protocol, port, folder):
|
||||
params = "format=json"
|
||||
if folder == "":
|
||||
url = f"{protocol}://{hostname}:{port}/{endpoint}/{user}?{params}"
|
||||
else:
|
||||
url = f"{protocol}://{hostname}:{port}/{folder}/{endpoint}/{user}?{params}"
|
||||
return url
|
||||
|
||||
|
||||
def get_session(username, secret):
|
||||
session = requests.session()
|
||||
session.cookies.set("SameSite", "Strict")
|
||||
session.auth = (username, secret)
|
||||
session.headers["Accept"] = "application/json"
|
||||
return session
|
||||
|
||||
|
||||
def get_data(session, url, verify):
|
||||
data = {}
|
||||
headers = CaseInsensitiveDict()
|
||||
headers["Accept"] = "application/json"
|
||||
response = session.get(url, headers=headers, verify=verify)
|
||||
status = response.status_code
|
||||
if status == 200:
|
||||
jsdata = response.text
|
||||
data = json.loads(jsdata) # returns a dictionary
|
||||
return data
|
||||
if status == 503:
|
||||
# this code is reported when maintenance mode is on
|
||||
sys.stderr.write(
|
||||
f"Request response code is {response.status_code} with URL {url}, maybe maintenance mode is on?\n"
|
||||
)
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.stderr.write(
|
||||
f"Request response code is {response.status_code} with URL {url}\n"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_data_all_users(session, url, verify):
|
||||
headers = CaseInsensitiveDict()
|
||||
headers["Accept"] = "application/json"
|
||||
headers["OCS-APIRequest"] = "true"
|
||||
response = session.get(url, headers=headers, verify=verify)
|
||||
status = response.status_code
|
||||
if status == 200:
|
||||
jsdata = response.text
|
||||
data = json.loads(jsdata) # returns a dictionary
|
||||
return data
|
||||
sys.stderr.write(
|
||||
f"Request response code is {response.status_code} with URL {url}\n"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_data_user(session, url, verify):
|
||||
headers = CaseInsensitiveDict()
|
||||
headers["Accept"] = "application/json"
|
||||
headers["OCS-APIRequest"] = "true"
|
||||
response = session.get(url, headers=headers, verify=verify)
|
||||
status = response.status_code
|
||||
if status == 200:
|
||||
jsdata = response.text
|
||||
data = json.loads(jsdata) # returns a dictionary
|
||||
return data
|
||||
|
||||
sys.stderr.write(
|
||||
f"Request response code is {response.status_code} with URL {url}\n"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def do_cmk_output(data):
|
||||
apps_with_updates_available = {}
|
||||
str_apps_with_updates_available = ""
|
||||
print("<<<nextcloud_info:sep(59)>>>")
|
||||
print(f"NC_Version;{data['ocs']['data']['nextcloud']['system']['version']}")
|
||||
print(f"NC_Freespace;{data['ocs']['data']['nextcloud']['system']['freespace']}")
|
||||
print(f"NC_Status;{data['ocs']['meta']['status']}")
|
||||
# This update info is available only from version 28 onwards, so the key "update" does not exist in all versions before
|
||||
try:
|
||||
print(
|
||||
f"NC_Last_Update;{data['ocs']['data']['nextcloud']['system']['update']['lastupdatedat']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Update_Available;{data['ocs']['data']['nextcloud']['system']['update']['available']}"
|
||||
)
|
||||
except KeyError:
|
||||
# TBD
|
||||
pass
|
||||
print(f"NC_Num_Users;{data['ocs']['data']['nextcloud']['storage']['num_users']}")
|
||||
print(f"NC_Num_Files;{data['ocs']['data']['nextcloud']['storage']['num_files']}")
|
||||
print(f"NC_Num_Shares;{data['ocs']['data']['nextcloud']['shares']['num_shares']}")
|
||||
print(
|
||||
f"NC_Num_Storages;{data['ocs']['data']['nextcloud']['storage']['num_storages']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Num_Storages_Home;{data['ocs']['data']['nextcloud']['storage']['num_storages_home']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Num_Storages_Local;{data['ocs']['data']['nextcloud']['storage']['num_storages_local']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Num_Storages_Other;{data['ocs']['data']['nextcloud']['storage']['num_storages_other']}"
|
||||
)
|
||||
# Workaround for Nextcloud 28.0.1 (KeyError "apps")
|
||||
try:
|
||||
print(
|
||||
f"NC_Num_Apps_Installed;{data['ocs']['data']['nextcloud']['system']['apps']['num_installed']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Num_Apps_Updates_Available;{data['ocs']['data']['nextcloud']['system']['apps']['num_updates_available']}"
|
||||
)
|
||||
apps_with_updates_available = data["ocs"]["data"]["nextcloud"]["system"][
|
||||
"apps"
|
||||
]["app_updates"]
|
||||
if apps_with_updates_available:
|
||||
for app, version in apps_with_updates_available.items():
|
||||
str_apps_with_updates_available = (
|
||||
str_apps_with_updates_available + app + "/" + version + " "
|
||||
)
|
||||
print(
|
||||
f"NC_Apps_With_Updates_Available;{str_apps_with_updates_available}"
|
||||
)
|
||||
except KeyError:
|
||||
# TBD
|
||||
pass
|
||||
print(
|
||||
f"NC_Active_Users_Last_5Min;{data['ocs']['data']['activeUsers']['last5minutes']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Active_Users_Last_1Hour;{data['ocs']['data']['activeUsers']['last1hour']}"
|
||||
)
|
||||
print(
|
||||
f"NC_Active_Users_Last_1Day;{data['ocs']['data']['activeUsers']['last24hours']}"
|
||||
)
|
||||
print(f"NC_Webserver;{data['ocs']['data']['server']['webserver']}")
|
||||
print(f"NC_PHP_Version;{data['ocs']['data']['server']['php']['version']}")
|
||||
|
||||
print("<<<nextcloud_database:sep(59)>>>")
|
||||
print(f"NC_Database_Type;{data['ocs']['data']['server']['database']['type']}")
|
||||
print(f"NC_Database_Version;{data['ocs']['data']['server']['database']['version']}")
|
||||
print(f"NC_Database_Size;{data['ocs']['data']['server']['database']['size']}")
|
||||
# opcache entry does not exist if opcache_get_status is disabled by server settings
|
||||
# thanks to Marcus Klein from Iteratio to report (and solve!) this bug
|
||||
if data["ocs"]["data"]["server"]["php"]["opcache"]:
|
||||
print(
|
||||
f"NC_OPCache_Hit_Rate;{data['ocs']['data']['server']['php']['opcache']['opcache_statistics']['opcache_hit_rate']}"
|
||||
)
|
||||
else:
|
||||
print("NC_OPCache_Hit_Rate;0")
|
||||
|
||||
|
||||
def do_cmk_output_all_users(session, data, verify, hostname, protocol, port, folder):
|
||||
print("<<<nextcloud_users:sep(59)>>>")
|
||||
for user in data["ocs"]["data"]["users"]:
|
||||
nc_url = create_url_user(
|
||||
user, NC_API_ENDPOINT_USER, hostname, protocol, port, folder
|
||||
)
|
||||
user_data = get_data_user(session, nc_url, verify)
|
||||
userid = user_data["ocs"]["data"]["id"]
|
||||
displayname = user_data["ocs"]["data"]["displayname"]
|
||||
lastlogin = int(user_data["ocs"]["data"]["lastLogin"])
|
||||
if lastlogin == 0:
|
||||
# user has never logged in
|
||||
quota_free = -1
|
||||
quota_quota = -1
|
||||
quota_relative = -1
|
||||
quota_total = -1
|
||||
quota_used = -1
|
||||
else:
|
||||
quota_free = user_data["ocs"]["data"]["quota"]["free"]
|
||||
# quota_quota == -3 --> unlimited
|
||||
quota_quota = user_data["ocs"]["data"]["quota"]["quota"]
|
||||
# quota_relative = used * 100 / (free + used)
|
||||
quota_relative = user_data["ocs"]["data"]["quota"]["relative"]
|
||||
quota_total = user_data["ocs"]["data"]["quota"]["total"]
|
||||
quota_used = user_data["ocs"]["data"]["quota"]["used"]
|
||||
print(
|
||||
f"{userid};{displayname};{lastlogin};{quota_free};{quota_quota};{quota_relative};{quota_total};{quota_used}"
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
# get and check parameters
|
||||
params: argparse.Namespace = get_args()
|
||||
if params.hostname is None:
|
||||
sys.stderr.write("No hostname given.\n")
|
||||
sys.exit(1)
|
||||
if params.username is None:
|
||||
sys.stderr.write("No username given.\n")
|
||||
sys.exit(1)
|
||||
if params.password is None:
|
||||
sys.stderr.write("No app password given.\n")
|
||||
sys.exit(1)
|
||||
hostname = params.hostname
|
||||
username = params.username
|
||||
pwd = params.password
|
||||
if params.folder is None:
|
||||
folder = ""
|
||||
else:
|
||||
folder = params.folder
|
||||
if params.no_cert_check:
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
verify = False
|
||||
else:
|
||||
verify = True
|
||||
if params.port is None:
|
||||
if params.no_https:
|
||||
protocol = "http"
|
||||
port = "80"
|
||||
else:
|
||||
protocol = "https"
|
||||
port = "443"
|
||||
else:
|
||||
if params.no_https:
|
||||
protocol = "http"
|
||||
else:
|
||||
protocol = "https"
|
||||
port = params.port
|
||||
if protocol == "http" and port == "443":
|
||||
sys.stderr.write("Combining HTTP with port 443 is not supported.\n")
|
||||
sys.exit(1)
|
||||
if protocol == "https" and port == "80":
|
||||
sys.stderr.write("Combining HTTPS with port 80 is not supported.\n")
|
||||
sys.exit(1)
|
||||
|
||||
# create session
|
||||
session = get_session(username, pwd)
|
||||
nc_url = create_url(NC_API_ENDPOINT, hostname, protocol, port, folder)
|
||||
nc_data = get_data(session, nc_url, verify)
|
||||
do_cmk_output(nc_data)
|
||||
nc_url = create_url(NC_API_ENDPOINT_ALL_USERS, hostname, protocol, port, folder)
|
||||
nc_data = get_data_all_users(session, nc_url, verify)
|
||||
do_cmk_output_all_users(session, nc_data, verify, hostname, protocol, port, folder)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
45
nextcloud/rulesets/nextcloud_database_rules.py
Normal file
45
nextcloud/rulesets/nextcloud_database_rules.py
Normal file
@ -0,0 +1,45 @@
|
||||
#!/user/bin/env python3
|
||||
"""parameter form ruleset for Nextcloud databases"""
|
||||
|
||||
from cmk.rulesets.v1 import Title
|
||||
from cmk.rulesets.v1.form_specs import (
|
||||
DefaultValue,
|
||||
DictElement,
|
||||
Dictionary,
|
||||
Float,
|
||||
LevelDirection,
|
||||
SimpleLevels,
|
||||
)
|
||||
from cmk.rulesets.v1.rule_specs import HostCondition, CheckParameters, Topic
|
||||
|
||||
|
||||
# function name should begin with an underscore to limit it's visibility
|
||||
def _parameter_form():
|
||||
return Dictionary(
|
||||
elements={
|
||||
"levels_database_opcache_hit_rate": DictElement(
|
||||
parameter_form=SimpleLevels(
|
||||
title=Title("Levels for database PHP op cache hit rate"),
|
||||
form_spec_template=Float(),
|
||||
level_direction=LevelDirection.LOWER,
|
||||
prefill_fixed_levels=DefaultValue(value=(95.0, 85.0)),
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||
# must be an instance of "CheckParameters"
|
||||
rule_spec_nextcloud_database = CheckParameters(
|
||||
# "name" should be the same as the check plugin
|
||||
name="nextcloud_database",
|
||||
# the title is shown in the GUI
|
||||
title=Title("Levels for database PHP op cache hit rate"),
|
||||
# this ruleset can be found under Setup|Service monitoring rules|Applications...
|
||||
topic=Topic.APPLICATIONS,
|
||||
# define the name of the function which creates the GUI elements
|
||||
parameter_form=_parameter_form,
|
||||
condition=HostCondition(),
|
||||
)
|
66
nextcloud/rulesets/nextcloud_info_rules.py
Normal file
66
nextcloud/rulesets/nextcloud_info_rules.py
Normal file
@ -0,0 +1,66 @@
|
||||
#!/user/bin/env python3
|
||||
"""parameter form ruleset for Nextcloud systems"""
|
||||
|
||||
from cmk.rulesets.v1 import Title
|
||||
from cmk.rulesets.v1.form_specs import (
|
||||
DefaultValue,
|
||||
DictElement,
|
||||
Dictionary,
|
||||
Float,
|
||||
LevelDirection,
|
||||
SimpleLevels,
|
||||
Integer,
|
||||
)
|
||||
from cmk.rulesets.v1.rule_specs import CheckParameters, Topic, HostCondition
|
||||
|
||||
|
||||
# function name should begin with an underscore to limit it's visibility
|
||||
def _parameter_form():
|
||||
return Dictionary(
|
||||
elements={
|
||||
"levels_apps_with_updates_available": DictElement(
|
||||
parameter_form=SimpleLevels(
|
||||
title=Title("Number of installed apps with updates available"),
|
||||
form_spec_template=Integer(),
|
||||
level_direction=LevelDirection.UPPER,
|
||||
prefill_fixed_levels=DefaultValue(value=(1, 2)),
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
"levels_free_space": DictElement(
|
||||
parameter_form=SimpleLevels(
|
||||
title=Title("Levels for free disk space overall"),
|
||||
form_spec_template=Float(unit_symbol="GBytes"),
|
||||
level_direction=LevelDirection.LOWER,
|
||||
prefill_fixed_levels=DefaultValue(value=(8.0, 4.0)),
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
"levels_number_of_files": DictElement(
|
||||
parameter_form=SimpleLevels(
|
||||
title=Title("Number of files overall"),
|
||||
form_spec_template=Integer(),
|
||||
level_direction=LevelDirection.UPPER,
|
||||
prefill_fixed_levels=DefaultValue(value=(100_000, 250_000)),
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||
# must be an instance of "CheckParameters"
|
||||
rule_spec_nextcloud_info = CheckParameters(
|
||||
# "name" should be the same as the check plugin
|
||||
name="nextcloud_info",
|
||||
# the title is shown in the GUI
|
||||
title=Title("Various parameters for Nextcloud systems"),
|
||||
# this ruleset can be found under Setup|Service monitoring rules|Applications...
|
||||
topic=Topic.APPLICATIONS,
|
||||
# define the name of the function which creates the GUI elements
|
||||
parameter_form=_parameter_form,
|
||||
# define the label in the GUI where you can restrict the
|
||||
# settings to one or mor specific storages (item)
|
||||
condition=HostCondition(),
|
||||
)
|
105
nextcloud/rulesets/nextcloud_params.py
Normal file
105
nextcloud/rulesets/nextcloud_params.py
Normal file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=line-too-long, missing-module-docstring
|
||||
|
||||
from cmk.rulesets.v1 import Help, Label, Title
|
||||
from cmk.rulesets.v1.form_specs import (
|
||||
BooleanChoice,
|
||||
DictElement,
|
||||
Dictionary,
|
||||
migrate_to_password,
|
||||
Password,
|
||||
String,
|
||||
Integer,
|
||||
validators,
|
||||
InputHint,
|
||||
)
|
||||
from cmk.rulesets.v1.rule_specs import SpecialAgent, Topic
|
||||
|
||||
|
||||
def _form_spec_special_agent_nextcloud() -> Dictionary:
|
||||
return Dictionary(
|
||||
title=Title("Nextcloud Server Information"),
|
||||
help_text=Help("Checking Nextcloud servers via API"),
|
||||
elements={
|
||||
"hostname": DictElement(
|
||||
required=True,
|
||||
parameter_form=String(
|
||||
title=Title("Hostname"),
|
||||
help_text=Help(
|
||||
"Hostname of Nextcloud server (bare FQDN or IP), mandatory, eg. nextcloud.yourdomain.tld"
|
||||
),
|
||||
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||
prefill=InputHint("nextcloud.yourdomain.tld"),
|
||||
),
|
||||
),
|
||||
"username": DictElement(
|
||||
required=True,
|
||||
parameter_form=String(
|
||||
title=Title("Username"),
|
||||
help_text=Help("Username with administrative rights, mandatory"),
|
||||
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||
prefill=InputHint("admin"),
|
||||
),
|
||||
),
|
||||
"password": DictElement(
|
||||
required=True,
|
||||
parameter_form=Password(
|
||||
title=Title("App Password"),
|
||||
help_text=Help(
|
||||
"Specify app password, mandatory, use Personal Settings|Security|Devices and Sessions within the NC UI to create one for the given user"
|
||||
),
|
||||
custom_validate=(validators.LengthInRange(min_value=1),),
|
||||
migrate=migrate_to_password,
|
||||
),
|
||||
),
|
||||
"port": DictElement(
|
||||
required=False,
|
||||
parameter_form=Integer(
|
||||
title=Title("Port"),
|
||||
help_text=Help(
|
||||
"Specify port if not listening to HTTP(S), optional"
|
||||
),
|
||||
prefill=InputHint(8080),
|
||||
custom_validate=(validators.NetworkPort(),),
|
||||
),
|
||||
),
|
||||
"folder": DictElement(
|
||||
required=False,
|
||||
parameter_form=String(
|
||||
title=Title("Folder"),
|
||||
help_text=Help(
|
||||
"Specify subfolder if your Nextcloud instance is not installed in the web root, no trailing/leading slashes, optional"
|
||||
),
|
||||
prefill=InputHint("nextcloud"),
|
||||
),
|
||||
),
|
||||
"no_https": DictElement(
|
||||
required=False,
|
||||
parameter_form=BooleanChoice(
|
||||
title=Title("Protocol handling"),
|
||||
label=Label("Disable HTTPS"),
|
||||
help_text=Help(
|
||||
"Activate to disable encryption (not recommended), optional"
|
||||
),
|
||||
),
|
||||
),
|
||||
"no_cert_check": DictElement(
|
||||
required=False,
|
||||
parameter_form=BooleanChoice(
|
||||
title=Title("Certificate handling"),
|
||||
label=Label("Disable certificate validation"),
|
||||
help_text=Help(
|
||||
"Activate to disable certificate validation (not recommended), optional"
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
rule_spec_nextcloud = SpecialAgent(
|
||||
name="nextcloud",
|
||||
title=Title("Nextcloud connection parameters"),
|
||||
topic=Topic.APPLICATIONS,
|
||||
parameter_form=_form_spec_special_agent_nextcloud,
|
||||
)
|
54
nextcloud/rulesets/nextcloud_users_rules.py
Normal file
54
nextcloud/rulesets/nextcloud_users_rules.py
Normal file
@ -0,0 +1,54 @@
|
||||
#!/user/bin/env python3
|
||||
"""parameter form ruleset for Nextcloud users"""
|
||||
|
||||
from cmk.rulesets.v1 import Title
|
||||
from cmk.rulesets.v1.form_specs import (
|
||||
DefaultValue,
|
||||
DictElement,
|
||||
Dictionary,
|
||||
Float,
|
||||
LevelDirection,
|
||||
SimpleLevels,
|
||||
)
|
||||
from cmk.rulesets.v1.rule_specs import HostAndItemCondition, CheckParameters, Topic
|
||||
|
||||
|
||||
# function name should begin with an underscore to limit it's visibility
|
||||
def _parameter_form():
|
||||
return Dictionary(
|
||||
elements={
|
||||
"levels_users_quota_used": DictElement(
|
||||
parameter_form=SimpleLevels(
|
||||
title=Title("Levels for quota usage of users"),
|
||||
form_spec_template=Float(unit_symbol="%"),
|
||||
level_direction=LevelDirection.UPPER,
|
||||
prefill_fixed_levels=DefaultValue(value=(65.0, 85.0)),
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
"levels_users_free_space": DictElement(
|
||||
parameter_form=SimpleLevels(
|
||||
title=Title("Levels for free disk space of users"),
|
||||
form_spec_template=Float(unit_symbol="MBytes"),
|
||||
level_direction=LevelDirection.LOWER,
|
||||
prefill_fixed_levels=DefaultValue(value=(256.0, 128.0)),
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# name must begin with "rule_spec_", should refer to the used check plugin
|
||||
# must be an instance of "CheckParameters"
|
||||
rule_spec_nextcloud_users = CheckParameters(
|
||||
# "name" should be the same as the check plugin
|
||||
name="nextcloud_users",
|
||||
# the title is shown in the GUI
|
||||
title=Title("Levels for Nextcloud users"),
|
||||
# this ruleset can be found under Setup|Service monitoring rules|Applications...
|
||||
topic=Topic.APPLICATIONS,
|
||||
# define the name of the function which creates the GUI elements
|
||||
parameter_form=_parameter_form,
|
||||
condition=HostAndItemCondition(item_title=Title("User ID")),
|
||||
)
|
54
nextcloud/server_side_calls/agent_nextcloud.py
Normal file
54
nextcloud/server_side_calls/agent_nextcloud.py
Normal file
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
# pylint: disable=missing-module-docstring, missing-class-docstring, missing-function-docstring
|
||||
|
||||
from collections.abc import Iterable
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from cmk.server_side_calls.v1 import (
|
||||
HostConfig,
|
||||
Secret,
|
||||
SpecialAgentCommand,
|
||||
SpecialAgentConfig,
|
||||
)
|
||||
|
||||
|
||||
class NextcloudParams(BaseModel):
|
||||
hostname: str | None = None
|
||||
username: str | None = None
|
||||
password: Secret | None = None
|
||||
port: int | None = None
|
||||
folder: str | None = None
|
||||
no_https: bool = False
|
||||
no_cert_check: bool = False
|
||||
|
||||
|
||||
def agent_nextcloud_arguments(
|
||||
params: NextcloudParams, _host_config: HostConfig
|
||||
) -> Iterable[SpecialAgentCommand]:
|
||||
# print(f"Params: {params}")
|
||||
command_arguments: list[str | Secret] = []
|
||||
if params.hostname is not None:
|
||||
command_arguments += ["--hostname", params.hostname]
|
||||
if params.username is not None:
|
||||
command_arguments += ["--username", params.username]
|
||||
if params.password is not None:
|
||||
command_arguments += ["--password", params.password.unsafe()]
|
||||
if params.port is not None:
|
||||
command_arguments += ["--port", str(params.port)]
|
||||
if params.folder is not None:
|
||||
command_arguments += ["--folder", params.folder]
|
||||
if params.no_https:
|
||||
command_arguments.append("--no-https")
|
||||
if params.no_cert_check:
|
||||
command_arguments.append("--no-cert-check")
|
||||
# command_arguments.append(host_config.name)
|
||||
# print(f"Command Args: {command_arguments}")
|
||||
yield SpecialAgentCommand(command_arguments=command_arguments)
|
||||
|
||||
|
||||
special_agent_nextcloud = SpecialAgentConfig(
|
||||
name="nextcloud",
|
||||
parameter_parser=NextcloudParams.model_validate,
|
||||
commands_function=agent_nextcloud_arguments,
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user