diff --git a/params.json b/params.json index 1cfd5e2..18057da 100644 --- a/params.json +++ b/params.json @@ -1,8 +1,13 @@ { - "nc_token": "", - "nc_db": "nextcloud_db", - "nc_host": "localhost", - "nc_db_port": 3306, - "ssl_enabled": false, - "hostname": "my.cloud.com" + "nc_token": "", + "nc_usr": "admin", + "nc_app_pwd": "", + "nc_host": "localhost", + "nc_db": "nextcloud_db", + "nc_db_port": 3306, + "nc_db_usr": "nextcloud_usr", + "nc_db_pwd": "", + "nc_db_host": "localhost", + "ssl_enabled": false, + "hostname": "my.cloud.com" } diff --git a/zabbix-agent-scripts/get_fts_indexing_status.py b/zabbix-agent-scripts/get_fts_indexing_status.py new file mode 100644 index 0000000..0b682bc --- /dev/null +++ b/zabbix-agent-scripts/get_fts_indexing_status.py @@ -0,0 +1,185 @@ +# +# @copyright Copyright (c) 2025, Pietro Marini (pmarini@rcasys.com) +# +# @license GNU AGPL version 3 or any later version +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +import random + +import json + +import string + +import sys + +import mariadb + +from reportlab.lib.pagesizes import A4 + +from reportlab.pdfgen.canvas import Canvas + +import logging + +import subprocess + +import time + +import os + +logging.basicConfig(stream=sys.stdout, level=logging.INFO) + +params = json.load(open("/var/lib/zabbix/params.json","r")) + +# create a series of string, then choose one that will be used to test the indexing +len_single_string = 12 + +random_strings = "" + +nr_strings = 5 + +for i in range(nr_strings): + + random_string = "".join(random.choices(string.ascii_letters + string.digits, k=len_single_string)) + + random_strings += " " + + random_strings += random_string + +test_string = random_strings.split()[random.randint(0,nr_strings-1)] + +logging.info("chosen string: {test_string}".format(test_string=test_string)) + +# create a pdf, file_test_fts_check.pdf, that contains this series of random strings +file_test_fts_check = "file_test_fts_check.pdf" + +my_pdf = Canvas(f"/tmp/{file_test_fts_check}", pagesize=A4) + +my_pdf.drawString(10,10,random_strings) + +my_pdf.save() + +# look the index for test_string, it should return no documents +########## IMPLEMENT ############ + +# upload file_test_fts_check.pdf +nc_usr = params["nc_usr"] + +nc_app_pwd = params["nc_app_pwd"] + +nc_url = f"http://{nc_usr}:{nc_app_pwd}@127.0.0.1:80/remote.php/dav/files/admin/{file_test_fts_check}" + +upload_cmd = f"curl --location --request PUT {nc_url} --header OCS-APIRequest: true --header Destination: {nc_url} --form file=@/tmp/{file_test_fts_check}" + +upload_file = subprocess.check_output(upload_cmd.split() + , stderr=subprocess.STDOUT) + +# give the system the time to index the file +time.sleep(10) + +# search test_string: only the, document testfile.pdf should be returned +search_cmd = f"occ fulltextsearch:search --output json admin {test_string}" + +search_file = subprocess.check_output(search_cmd.split() + , stderr=subprocess.STDOUT) + +# check that there is a single entry in the result set +search_result_set = json.loads(search_file.decode())["files"] + +fts_indexing_status = {} + +fts_indexing_status["fts_indexing_status"] = "ko" + +if len(search_result_set)!=1: + + logging.info("FTS: no file or more than one file has been found. Check the FTS indexing system.") + +else: + + search_ft_file_id = search_result_set[0]["id"] + + logging.info(f"FTS returned file with ID: {search_ft_file_id}") + + # compare to the file id as found in oc_filecache + try: + conn = mariadb.connect( + user=params["nc_db_usr"], + password=params["nc_db_pwd"], + host=params["nc_db_host"], + port=params["nc_db_port"], + database=params["nc_db"] + ) + + except mariadb.Error as e: + logging.info(f"Error connecting to database: {e}") + sys.exit(1) + + cur = conn.cursor() + + cur.execute( + f""" + select fileid from oc_filecache + where path = 'files/{file_test_fts_check}' + and storage = (select numeric_id from oc_storages where id = 'home::{nc_usr}') + """ + ) + + # check that there is a single entry in the result set + db_search_result_set = cur.fetchall() + + if len(db_search_result_set) != 1: + + logging.info("DB Search: no file or more than one file has been found. Check the FTS indexing system.") + + else: + + search_db_file_id = db_search_result_set[0][0] + + logging.info(f"DB Search returned file with ID: {search_db_file_id}") + + if str(search_db_file_id).strip() == str(search_ft_file_id).strip(): + + logging.info("Check is ok.") + + fts_indexing_status["fts_indexing_status"] = "ok" + +################### +# report the result +################### +logging.info("writing the result of the check") + +with open("/var/lib/zabbix/output/fts_indexing_status.json","w") as file_output_fts_check: + + json.dump(fts_indexing_status, file_output_fts_check) + +logging.info("ok") + +################### +# clean-up, delete {file_test_fts_check} locally and on Nextcloud +################### +logging.info(f"removing {file_test_fts_check} from Nextcloud") + +delete_cmd = f"curl --location --request DELETE {nc_url} --header OCS-APIRequest: true --header Destination: {nc_url}" + +delete_file = subprocess.check_output(delete_cmd.split() + , stderr=subprocess.STDOUT) + +logging.info("ok") + +logging.info(f"removing {file_test_fts_check} from the local temporary folder") + +os.remove(f"/tmp/{file_test_fts_check}") + +logging.info("ok") diff --git a/zabbix-templates/6.0/nextcloud-zabbix-template.json b/zabbix-templates/6.0/nextcloud-zabbix-template.json index 747157c..767e835 100644 --- a/zabbix-templates/6.0/nextcloud-zabbix-template.json +++ b/zabbix-templates/6.0/nextcloud-zabbix-template.json @@ -1,7 +1,7 @@ { "zabbix_export": { "version": "6.0", - "date": "2025-07-04T14:08:30Z", + "date": "2025-09-01T09:03:39Z", "groups": [ { "uuid": "18fce3c341e74778ba11126e46a87ebd", @@ -17,7 +17,7 @@ "uuid": "eddea30a51d94d56875d2dd78fab8120", "template": "Nextcloud", "name": "Nextcloud", - "description": "Nextcloud by RCA Systems\nVersion: 6.0-1.0", + "description": "Nextcloud by RCA Systems", "groups": [ { "name": "Nextcloud Installation" @@ -36,6 +36,31 @@ "value_type": "TEXT" }, { + "uuid": "d11ef64f780346aa955d6d87518166a8", + "name": "Full Text Search Indexing Status", + "key": "fts_indexing_status", + "delay": "30m", + "trends": "0", + "value_type": "TEXT", + "description": "Full Text Search Indexing Status", + "preprocessing": [ + { + "type": "JSONPATH", + "parameters": [ + "$.fts_indexing_status" + ] + } + ], + "triggers": [ + { + "uuid": "69084c29522e4e97988d761119ba7f09", + "expression": "last(/Nextcloud/fts_indexing_status)<>\"ok\"", + "name": "Full Text Search - Indexing status check fails", + "priority": "AVERAGE" + } + ] + }, + { "uuid": "8bfc17be6a414c5ca715e46ebca038f8", "name": "Number of Users - Active in Last Hour", "key": "nc_metric[ocs.data.activeUsers.last1hour]", @@ -480,6 +505,12 @@ ] } ], + "macros": [ + { + "macro": "{$TEMPLATE_VERSION}", + "value": "{\"vendor\": { \"name\": \"RCA Systems\", \"version\": \"6.0-1.1.0\"}}" + } + ], "dashboards": [ { "uuid": "ebbdaed351ae43baa35a816e2a8cc048", @@ -1958,4 +1989,4 @@ } ] } -} \ No newline at end of file +} diff --git a/zabbix-templates/7.0/nextcloud-zabbix-template.json b/zabbix-templates/7.0/nextcloud-zabbix-template.json index 67f0837..e06c728 100644 --- a/zabbix-templates/7.0/nextcloud-zabbix-template.json +++ b/zabbix-templates/7.0/nextcloud-zabbix-template.json @@ -19,7 +19,7 @@ "description": "Nextcloud by RCA Systems", "vendor": { "name": "RCA Systems", - "version": "7.0-1.0" + "version": "7.0-1.1.0" }, "groups": [ { @@ -40,6 +40,32 @@ "trends": "0" }, { + "uuid": "2bb93cac134b4fd09e5e3ea5d7cf19e2", + "name": "Full Text Search Indexing Status", + "key": "fts_indexing_status", + "delay": "30m", + "value_type": "TEXT", + "trends": "0", + "description": "Full Text Search Indexing Status", + "preprocessing": [ + { + "type": "JSONPATH", + "parameters": [ + "$.fts_indexing_status" + ] + } + ], + "triggers": [ + { + "uuid": "e4118f4e06624abbb08e8941ce8ae56f", + "expression": "last(/Nextcloud/fts_indexing_status)<>\"ok\"", + "name": "Full Text Search - Indexing status check fails", + "priority": "AVERAGE", + "manual_close": "YES" + } + ] + }, + { "uuid": "8bfc17be6a414c5ca715e46ebca038f8", "name": "Number of Users - Active in Last Hour", "key": "nc_metric[ocs.data.activeUsers.last1hour]", @@ -376,6 +402,7 @@ "delay": "1h", "history": "90d", "value_type": "FLOAT", + "description": "Storage Quota (GB) - Assigned Total for Team Folders", "preprocessing": [ { "type": "JSONPATH", @@ -1497,11 +1524,6 @@ "type": "INTEGER", "name": "show", "value": "3" - }, - { - "type": "INTEGER", - "name": "time_size", - "value": "20" } ] }, diff --git a/zabbix_agentd.conf.d/zabbix-agent-nextcloud.conf b/zabbix_agentd.conf.d/zabbix-agent-nextcloud.conf index 5a6e608..a6fb091 100644 --- a/zabbix_agentd.conf.d/zabbix-agent-nextcloud.conf +++ b/zabbix_agentd.conf.d/zabbix-agent-nextcloud.conf @@ -7,3 +7,4 @@ UserParameter=db_metric_discovery,/opt/pyvenv/ncmonitor/bin/python /var/lib/zabbix/scripts/discover_db_metrics.py UserParameter=apache2_user_agent_metric_discovery,/opt/pyvenv/ncmonitor/bin/python /var/lib/zabbix/scripts/discover_apache2_user_agent_metrics.py UserParameter=apache2_user_agent_metric[*],/opt/pyvenv/ncmonitor/bin/python /var/lib/zabbix/scripts/read_apache2_user_agent_metrics.py $1 +UserParameter=fts_indexing_status,cat /var/lib/zabbix/output/fts_indexing_status.json