Cacti Restuful API V0.1 (#6310)

* inital commit

* remove composer files

* Update api/public/index.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update api/include/db_functions.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Add API Versioning

- Group Endpoint types together
- Add initial V1 endpoint groups
- Leverage the slim  route collector class

* Migrate db functions to Cacti core  db functions

* remove dedicated config file

* Update README.md

* Update db_functions.php

- include global and not the lib/database
- remove redudant db_connect function

* Sanity checks

- Ensure arrays are initialized before iterating

* Update db_functions.php

* Add logging

* helper function for parameter validation

* Update api/include/db_functions.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Sanitize error message

* Update db_functions.php

use the proper cacti db function
Leverage the read_config_option function instead of standalone db query

* Update api/include/db_functions.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Cleaning up  from pre migration to core cacti functions

* clean up

* update tholds endpoint

Call on the validate parameters helper function

* call on db_fetch_cell for thold db_function

* Update api/public/index.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Creat automation networks api endpoint

Call the proper db prepared function for prepared statments

* automation status endpoint

* data source stats status endpoint

* add validations (more to come)

* validations

* Update api/include/arrays.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update api/include/db_functions.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update api/include/arrays.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update api/include/db_functions.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor validation error handling in API routes

This changes adds a small bit of PSR formatting to the code, and reduces the length of the $validation_error by renaming to $verror for redability.

* Clean up whitespace in arrays.php

* Refactor SQL queries for improved readability

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
This commit is contained in:
authored and GitHub committed 2025-09-11 13:06:45 -04:00
1 parent 697e231ea5
commit 6de44a0fe7
5 files changed
+832

No files matched your search

+81
View File
@@ -0,0 +1,81 @@
# Cacti RESTful Slim API
This project provides a RESTful API for accessing Cacti monitoring data using the Slim PHP framework.
## Overview
The API exposes endpoints to retrieve information about hosts, host templates, poller status, graph lists, Cacti status, boost status, database connectivity, and plugin thresholds. All responses are in JSON format.
THIS IS NOT PROD READY!
To run the API php -S 127.0.0.1:8080 -t public ( Which for Prod will be replaced with a WSGI server)
## API Versioning
The API uses URL path versioning. All endpoints are prefixed with a version number:
- `/v1/` - Current stable version
## Endpoints
- `GET /`
Returns a welcome message.
### Version 1 (v1) Endpoints
#### Info Endpoints
- `GET /v1/info/hosts`
Returns a list of hosts.
**Allowed query parameters:**
- `host_id`
- `poller_id`
- `site_id`
- `template_id`
- `status`
- `GET /v1/info/host_templates`
Returns host template information. Accepts `template_id` as a query parameter.
- `GET /v1/info/graph_list`
Returns a list of graphs. Accepts `host_id` as a query parameter.
#### Status Endpoints
- `GET /v1/status/poller_status`
Returns poller status. Accepts `poller_id` as a query parameter.
- `GET /v1/status/cacti_status`
Returns the status of the Cacti system.
- `GET /v1/status/boost_status`
Returns the status of the Cacti Boost system.
- `GET /v1/status/api_db_ping`
Checks database connectivity.
- `GET /v1/status/cacti_db_status`
Returns some metrics of the Main cacti DB
#### Plugin Endpoints
- `GET /v1/plugin/thold/thresholds`
Returns threshold information from the thold plugin.
- `GET /v1/plugin/thold/status`
Returns threshold status information.
## Usage
1. Install dependencies with Composer.
2. Configure your web server to serve the `public/` directory.
3. Access the API endpoints as described above using the versioned URLs (e.g., `/v1/info/hosts`).
## Requirements
- PHP 7.4 or higher
- Composer
- Cacti database and configuration
## TODO
- Import Cacti base db_functions
- Logging
- Authentication/Authorization
- Rate limiting
- API documentation (OpenAPI/Swagger)
+6
View File
@@ -0,0 +1,6 @@
{
"require": {
"slim/slim": "^4.14",
"slim/psr7": "^1.7"
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
$allowed_hosts_filter = [
'host_id',
'poller_id',
'site_id',
'template_id',
'status',
'snmp_location',
'hostname',
'description'
];
$allowed_host_templates_filter = [
'template_id'
];
$allowed_thold_filter = [
'host_id',
'host_description',
'hostname',
'data_source_name',
'template_id'
];
$allowed_automation_networks_filter = [
'network_id',
'network_name',
'subnet_range',
];
+491
View File
@@ -0,0 +1,491 @@
<?php
function get_hosts($params = []) {
$sql = "SELECT id as host_id, description as host_description, hostname, host_template_id,
poller_id, site_id, disabled, status, status_fail_date AS last_fail_date,
status_rec_date AS last_recovery_date, status_last_error AS last_error,
availability, polling_time, total_polls, failed_polls, snmp_sysDescr AS snmp_description,
snmp_sysUpTimeInstance AS snmp_uptime, snmp_sysLocation AS snmp_location, last_updated
FROM host";
$conditions = [];
$values = [];
if (isset($params['host_id']) && $params['host_id'] !== '') {
if (!is_array($params['host_id'])) {
$params['host_id'] = explode(',', $params['host_id']);
}
$params['host_id'] = array_map('trim', $params['host_id']);
$params['host_id'] = array_filter($params['host_id'], fn($v) => $v !== '');
if (!empty($params['host_id'])) {
$placeholders = implode(',', array_fill(0, count($params['host_id']), '?'));
$conditions[] = "id IN ($placeholders)";
$values = array_merge($values, $params['host_id']);
}
}
if (isset($params['poller_id']) && $params['poller_id'] !== '') {
if (!is_array($params['poller_id'])) {
$params['poller_id'] = explode(',', $params['poller_id']);
}
$params['poller_id'] = array_map('trim', $params['poller_id']);
$params['poller_id'] = array_filter($params['poller_id'], fn($v) => $v !== '');
if (!empty($params['poller_id'])) {
$placeholders = implode(',', array_fill(0, count($params['poller_id']), '?'));
$conditions[] = "poller_id IN ($placeholders)";
$values = array_merge($values, $params['poller_id']);
}
}
if (isset($params['site_id']) && $params['site_id'] !== '') {
if (!is_array($params['site_id'])) {
$params['site_id'] = explode(',', $params['site_id']);
}
$params['site_id'] = array_map('trim', $params['site_id']);
$params['site_id'] = array_filter($params['site_id'], fn($v) => $v !== '');
if (!empty($params['site_id'])) {
$placeholders = implode(',', array_fill(0, count($params['site_id']), '?'));
$conditions[] = "site_id IN ($placeholders)";
$values = array_merge($values, $params['site_id']);
}
}
if (isset($params['template_id']) && $params['template_id'] !== '') {
if (!is_array($params['template_id'])) {
$params['template_id'] = explode(',', $params['template_id']);
}
$params['template_id'] = array_map('trim', $params['template_id']);
$params['template_id'] = array_filter($params['template_id'], fn($v) => $v !== '');
if (!empty($params['template_id'])) {
$placeholders = implode(',', array_fill(0, count($params['template_id']), '?'));
$conditions[] = "host_template_id IN ($placeholders)";
$values = array_merge($values, $params['template_id']);
}
}
if (isset($params['status'])) {
$conditions[] = "status = ?";
$values[] = $params['status'];
}
if (isset($params['snmp_location'])) {
$conditions[] = "snmp_sysLocation LIKE ?";
$values[] = '%' . $params['snmp_location'] . '%';
}
// Apply WHERE clause if needed
if (!empty($conditions)) {
$sql .= " WHERE " . implode(" AND ", $conditions);
}
return $values ? db_fetch_assoc_prepared($sql, $values) : db_fetch_assoc($sql);
}
/**
* Retrieves a list of graphs associated with a specific host.
*
* This function queries the database to fetch graph details for a given host ID.
* It returns an array of graphs, each containing the host ID, graph ID, and RRD name.
*
* @param int $host_id The ID of the host for which to retrieve the graph list. Defaults to 0.
*
* @return array An associative array with the key "graphs" containing a list of graphs.
* Each graph is represented as an associative array with the following keys:
* - "host_id" (int): The ID of the host.
* - "graph_id" (int): The ID of the graph.
* - "rrd_name" (string): The name of the RRD file.
*/
function get_graph_list($host_id = 0) {
if (filter_var($host_id, FILTER_VALIDATE_INT) === false || $host_id < 0) {
return ["graphs" => ["Host must be a valid INT"]];
}
$sql = "SELECT DISTINCT h.id as host_id, dl.id as graph_id, dtd.name_cache as rrd_name, pi.rrd_name as rrd_path
FROM poller_item AS pi
INNER JOIN data_local AS dl
ON dl.id = pi.local_data_id
INNER JOIN data_template_data AS dtd
ON dtd.local_data_id = pi.local_data_id
INNER JOIN host AS h
ON pi.host_id = h.id
WHERE rrd_name != ''
AND h.id = ?";
$rows = db_fetch_assoc_prepared($sql, [$host_id]);
$graphs = [];
if (is_array($rows)) {
foreach ($rows as $row) {
$graphs[] = [
"host_id" => $row['host_id'],
"graph_id" => $row['graph_id'],
"rrd_name" => $row['rrd_name']
];
}
}
return ["graphs" => $graphs];
}
function get_poller_status($poller_id = 0) {
if (filter_var($poller_id, FILTER_VALIDATE_INT) === false || $poller_id < 0) {
return ["error" => "Poller ID must be a valid INT"];
}
$sql = "SELECT id, name, disabled, status, hostname, total_time, max_time,
min_time, avg_time, total_polls, processes, threads, last_update, last_status
FROM poller";
$values = [];
if ($poller_id > 0) {
$sql .= " WHERE id = ?";
$values[] = $poller_id;
}
return $values ? db_fetch_assoc_prepared($sql, $values) : db_fetch_assoc($sql);
}
function get_host_templates($template_id = 0) {
if (filter_var($template_id, FILTER_VALIDATE_INT) === false || $template_id < 0) {
return ["templates" => ["Template ID must be a valid INT"]];
}
$sql = 'SELECT id,name,class FROM host_template';
$values = [];
if ($template_id > 0) {
$sql .= ' WHERE id = ?';
$values[] = $template_id;
}
return $values ? db_fetch_assoc_prepared($sql, $values) : db_fetch_assoc($sql);
}
function get_cacti_status() {
// Get Cacti version
$cacti_version = db_fetch_cell("SELECT cacti AS version FROM version LIMIT 1");
$poller_type = read_config_option('poller_type');
$poller_enabled = read_config_option('poller_enabled');
$total_hosts = db_fetch_cell("SELECT COUNT(*) as count FROM host");
$total_data_sources = db_fetch_cell("SELECT COUNT(*) as count FROM data_local");
$poller_output_size = db_fetch_cell("SELECT COUNT(*) as count FROM poller_output");
$boost_table_size = db_fetch_cell("SELECT COUNT(*) as count FROM poller_output_boost");
if ($poller_enabled === "on") {
$poller_enabled = "Global Polling is enabled";
} else {
$poller_enabled = "Global polling is disabled";
}
$poller_type = ($poller_type === "2") ? "Spine" : (($poller_type === "1") ? "cmd.php" : $poller_type);
// Get installed plugins
$plugins = db_fetch_assoc("SELECT name, status, version FROM plugin_config");
$installed_plugins = [];
if (is_array($plugins)) {
foreach ($plugins as $plugin) {
$status = ($plugin['status'] == 1) ? "enabled" : "disabled";
$installed_plugins[] = [
"name" => $plugin['name'],
"status" => $status,
"version" => $plugin['version']
];
}
}
$cacti_status = [
[
"cacti_version" => $cacti_version,
"poller_type" => $poller_type,
"poller_enabled" => $poller_enabled,
"total_hosts" => $total_hosts,
"poller_output_size" => $poller_output_size,
"boost_table_size" => $boost_table_size,
"total_data_sources" => $total_data_sources,
"installed_plugins" => $installed_plugins
]
];
return ["cacti_status" => $cacti_status];
}
function get_boost_status() {
$boost_rrd_update_enable = read_config_option('boost_rrd_update_enable');
if ($boost_rrd_update_enable !== 'on') {
return ['boost_rrd_update_enable' => 'Boost is disabled'];
}
$boost_last_end_time = read_config_option('boost_last_end_time');
$boost_last_start_time = read_config_option('boost_last_start_time');
$boost_next_run_time = read_config_option('boost_next_run_time');
$stats_detail_boost = read_config_option('stats_detail_boost');
$total_boost_records = db_fetch_cell("SELECT COUNT(*) as count FROM poller_output_boost");
$boost_status = [
"boost_rrd_update_enable" => $boost_rrd_update_enable,
"boost_last_end_time" => $boost_last_end_time,
"boost_last_start_time" => $boost_last_start_time,
"boost_next_run_time" => $boost_next_run_time,
"stats_detail_boost" => $stats_detail_boost,
"total_boost_records" => $total_boost_records
];
return ["boost_status" => $boost_status];
}
function get_dsstats_status() {
$check_dsstats_enabled = read_config_option('dsstats_enable');
if ($check_dsstats_enabled !== 'on') {
return ['dsstats_status' => 'Data Source Statistics is disabled'];
}
$dssatst_status = [
"dsstats_poller_memory_limit" => read_config_option('dsstats_poller_mem_limit'),
"dsstats_timeout" => read_config_option('dsstats_timeout'),
"dsstats_parallel_processes" => read_config_option('dsstats_parallel'),
"dsstats_mode" => (read_config_option('dsstats_mode') == 0 ? "Peak/Average Only" : "All Metrics"),
"dsstats_hourly_duration" => read_config_option('dsstats_hourly_duration'),
"dsstats_daily_interval" => read_config_option('dsstats_daily_interval'),
"dsstats_weekly_retention" => read_config_option('dsstats_weekly_retention'),
"dsstats_monthly_retention" => read_config_option('dsstats_monthly_retention'),
"dsstats_yearly_retention" => read_config_option('dsstats_yearly_retention'),
"dsstats_last_run_time" => read_config_option('dsstats_last_major_run_time'),
"dsstats_peak" => read_config_option('dsstats_peak'),
];
return ["dsstats_status" => $dsstats_status];
}
function get_cacti_db_status() {
$status_rows = db_fetch_assoc("SHOW STATUS");
$status_assoc = [];
foreach ($status_rows as $row) {
if (isset($row['Variable_name']) && isset($row['Value'])) {
$status_assoc[$row['Variable_name']] = $row['Value'];
}
}
$db_status = [
"max_used_connections" => $status_assoc['Max_used_connections'] ?? 0,
"threads_connected" => $status_assoc['Threads_connected'] ?? 0,
"threads_running" => $status_assoc['Threads_running'] ?? 0,
"Aborted_clients" => $status_assoc['Aborted_clients'] ?? 0,
"Aborted_connects" => $status_assoc['Aborted_connects'] ?? 0,
"Uptime" => $status_assoc['Uptime'] ?? 0,
"innodb_buffer_pool_size" => $status_assoc['Innodb_buffer_pool_size'] ?? 0,
"innodb_buffer_pool_pages_total" => $status_assoc['Innodb_buffer_pool_pages_total'] ?? 0,
"innodb_buffer_pool_pages_free" => $status_assoc['Innodb_buffer_pool_pages_free'] ?? 0,
"innodb_buffer_pool_pages_data" => $status_assoc['Innodb_buffer_pool_pages_data'] ?? 0,
"innodb_buffer_pool_pages_dirty" => $status_assoc['Innodb_buffer_pool_pages_dirty'] ?? 0
];
return ["db_status" => $db_status];
}
function get_thresholds($params = []) {
$check_thold_installed = db_fetch_assoc("SHOW TABLES LIKE 'thold_data'");
if (empty($check_thold_installed)) {
return ["thold_status" => "Thresholds plugin is not installed"];
}
$sql = "SELECT h.id as HOST_ID, description AS HOST_DESCRIPTION, h.hostname, data_source_name, thold_hi, thold_low, lastread, lastchanged, thold_fail_count, thold_enabled
FROM thold_data td
INNER JOIN host h
ON td.host_id = h.id";
$conditions = [];
$values = [];
if (isset($params['host_id']) && $params['host_id'] !== '') {
if (!is_array($params['host_id'])) {
$params['host_id'] = explode(',', $params['host_id']);
}
$params['host_id'] = array_map('trim', $params['host_id']);
$params['host_id'] = array_filter($params['host_id'], fn($v) => $v !== '');
if (!empty($params['host_id'])) {
$placeholders = implode(',', array_fill(0, count($params['host_id']), '?'));
$conditions[] = "h.id IN ($placeholders)";
$values = array_merge($values, $params['host_id']);
}
}
if (isset($params["host_description"])) {
$conditions[] = "h.description LIKE ?";
$values[] = '%' . $params['host_description'] . '%';
}
if (isset($params["hostname"])) {
$conditions[] = "h.hostname LIKE ?";
$values[] = '%' . $params['hostname'] . '%';
}
if (isset($params['data_source_name'])) {
$conditions[] = "td.data_source_name LIKE ?";
$values[] = '%' . $params['data_source_name'] . '%';
}
if (isset($params['template_id']) && $params['template_id'] !== '') {
if (!is_array($params['template_id'])) {
$params['template_id'] = explode(',', $params['template_id']);
}
$params['template_id'] = array_map('trim', $params['template_id']);
$params['template_id'] = array_filter($params['template_id'], fn($v) => $v !== '');
if (!empty($params['template_id'])) {
$placeholders = implode(',', array_fill(0, count($params['template_id']), '?'));
$conditions[] = "host_template_id IN ($placeholders)";
$values = array_merge($values, $params['template_id']);
}
}
if (!empty($conditions)) {
$sql .= " WHERE " . implode(" AND ", $conditions);
}
$rows = $values ? db_fetch_assoc_prepared($sql, $values) : db_fetch_assoc($sql);
$thresholds = [];
if (is_array($rows)) {
foreach ($rows as $row) {
$thresholds[] = [
"host_id" => $row['HOST_ID'],
"host_description" => $row['HOST_DESCRIPTION'],
"hostname" => $row['hostname'],
"data_source_name" => $row['data_source_name'],
"thold_hi" => $row['thold_hi'],
"thold_low" => $row['thold_low'],
"lastread" => $row['lastread'],
"lastchanged" => $row['lastchanged'],
"thold_fail_count" => $row['thold_fail_count'],
"thold_enabled" => $row['thold_enabled']
];
}
}
return ["thresholds" => $thresholds];
}
function get_threshold_status() {
$check_thold_installed = db_fetch_assoc("SHOW TABLES LIKE 'thold_data'");
if (empty($check_thold_installed)) {
return ["thold_status" => "Thresholds plugin is not installed"];
}
$check_daemon_enabled = read_config_option('thold_daemon_enable');
$daemon_status = [];
if (empty($check_daemon_enabled)) {
$daemon_status = ["thold_status" => "Thold daemon is not enabled"];
} else {
$daemon_status = [
"thold_daemon_dead_notification" => read_config_option('thold_daemon_dead_notification'),
"thold_daemon_debug" => (read_config_option('thold_daemon_debug') === 'on') ? 'enabled' : 'disabled',
"thold_daemon_down_notify_time" => read_config_option('thold_daemon_down_notify_time'),
"thold_daemon_enable" => ($check_daemon_enabled === 'on') ? 'enabled' : 'disabled'
];
}
$poller_stats = read_config_option('stats_thold');
$total_thresholds = db_fetch_cell("SELECT COUNT(*) as cnt FROM thold_data") ?? 0;
$enabled_thresholds = db_fetch_cell("SELECT COUNT(*) as cnt FROM thold_data WHERE thold_enabled = 1") ?? 0;
$disabled_thresholds = db_fetch_cell("SELECT COUNT(*) as cnt FROM thold_data WHERE thold_enabled = 0") ?? 0;
return [
"thold_status" => [
"daemon" => $daemon_status,
"poller_stats" => $poller_stats,
"total_thresholds" => $total_thresholds,
"enabled_thresholds" => $enabled_thresholds,
"disabled_thresholds" => $disabled_thresholds
]
];
}
// automation functions
function get_automation_networks($params = []) {
$sql = "SELECT id, poller_id, name, subnet_range, ignore_ips, dns_servers, enabled,
notification_email, up_hosts, snmp_hosts, ping_method, ping_timeout, ping_retries,
start_at, next_start, last_runtime, last_started, last_status
FROM automation_networks";
$conditions = [];
$values = [];
if (isset($params['network_id']) && $params['network_id'] !== '') {
if (!is_array($params['network_id'])) {
$params['network_id'] = explode(',', $params['network_id']);
}
$params['network_id'] = array_map('trim', $params['network_id']);
$params['network_id'] = array_filter($params['network_id'], fn($v) => $v !== '');
if (!empty($params['network_id'])) {
$placeholders = implode(',', array_fill(0, count($params['network_id']), '?'));
$conditions[] = "id IN ($placeholders)";
$values = array_merge($values, $params['network_id']);
}
}
if (isset($params['network_name']) && $params['network_name'] !== '') {
$conditions[] = "name LIKE ?";
$values[] = '%' . $params['network_name'] . '%';
}
if (isset($params['subnet_range']) && $params['subnet_range'] !== '') {
$conditions[] = "subnet_range LIKE ?";
$values[] = '%' . $params['subnet_range'] . '%';
}
if (!empty($conditions)) {
$sql .= " WHERE " . implode(" AND ", $conditions);
}
// Use prepared variant when values exist (placeholders present)
if (!empty($values)) {
return db_fetch_assoc_prepared($sql, $values);
}
return db_fetch_assoc($sql);
}
function get_automation_status() {
$sql = "SELECT DISTINCT ap.network_id, an.name, an.subnet_range, an.last_started
FROM automation_processes ap
INNER JOIN automation_networks an ON ap.network_id = an.id";
$rows = db_fetch_assoc($sql);
$automation_status = [];
if (is_array($rows)) {
foreach ($rows as $row) {
$automation_status[] = [
"network_id" => $row['network_id'],
"network_name" => $row['name'],
"subnet_range" => $row['subnet_range'],
"last_started" => $row['last_started']
];
}
}
return ["running_automations" => $automation_status];
}
+224
View File
@@ -0,0 +1,224 @@
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteCollectorProxy;
include __DIR__ . '/../include/db_functions.php';
include __DIR__ . '/../include/arrays.php';
include '../../include/global.php';
$client_ip = $_SERVER['REMOTE_ADDR'];
$app = AppFactory::create();
$app->addErrorMiddleware(true, true, true);
$app->get("/", function (Request $request, Response $response) {
$response->getBody()->write("Welcome to the Cacti API!");
return $response;
});
/**
* Validates that all provided parameters are within the allowed parameter list.
*
* This function checks each parameter key against a list of allowed parameters
* and returns an error message if any invalid parameters are found.
*
* @param array $params The parameters to validate (key-value pairs)
* @param array $allowed_params Array of allowed parameter names
* @return string|null Returns an error message if invalid parameters are found, otherwise null
*/
function validate_parameters($params, $allowed_params) {
foreach ($params as $key => $value) {
if (!in_array($key, $allowed_params)) {
return 'ERROR: Invalid parameter passed: "' . htmlspecialchars($key) . '"';
}
}
return null;
}
// V1 API Routes Group
$app->group('/v1', function (RouteCollectorProxy $group) {
// Info endpoints
$group->group('/info', function (RouteCollectorProxy $infoGroup) {
$infoGroup->get('/hosts', function (Request $request, Response $response) {
global $allowed_hosts_filter, $client_ip;
$params = $request->getQueryParams();
$verror = validate_parameters($params, $allowed_hosts_filter);
if ($verror) {
$response->getBody()->write(json_encode($verror));
cacti_log($verror . " By HOST: " . $client_ip, false, 'API');
return $response->withStatus(400)->withHeader('Content-Type', 'application/json');
}
$json = json_encode(get_hosts($params));
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$infoGroup->get('/host_templates', function (Request $request, Response $response) {
global $allowed_host_templates_filter, $client_ip;
$params = $request->getQueryParams();
$verror = validate_parameters($params, $allowed_host_templates_filter);
if ($verror) {
$response->getBody()->write(json_encode($verror));
cacti_log($verror . " By HOST: " . $client_ip, false, 'API');
return $response->withStatus(400)->withHeader('Content-Type', 'application/json');
}
$json = json_encode(get_host_templates($params['template_id'] ?? 0));
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$infoGroup->get('/graph_list', function (Request $request, Response $response) {
$params = $request->getQueryParams();
$host_id = $params['host_id'] ?? 0;
$json = json_encode(get_graph_list($host_id));
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$infoGroup->get('/automation_networks', function (Request $request, Response $response) {
global $allowed_automation_networks_filter, $client_ip;
$params = $request->getQueryParams();
$verror = validate_parameters($params, $allowed_automation_networks_filter);
if ($verror) {
$response->getBody()->write(json_encode($verror));
cacti_log($verror . " By HOST: " . $client_ip, false, 'API');
return $response->withStatus(400)->withHeader('Content-Type', 'application/json');
}
$json = json_encode(get_automation_networks($params));
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
});
// Status endpoints
$group->group('/status', function (RouteCollectorProxy $statusGroup) {
$statusGroup->get('/poller_status', function (Request $request, Response $response) {
$params = $request->getQueryParams();
$poller_id = $params['poller_id'] ?? 0;
$hosts = get_poller_status($poller_id);
$response->getBody()->write(json_encode($hosts));
return $response->withHeader('Content-Type', 'application/json');
});
$statusGroup->get('/cacti_status', function (Request $request, Response $response) {
$json = json_encode(get_cacti_status());
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$statusGroup->get('/cacti_db_status', function (Request $request, Response $response) {
$json = json_encode(get_cacti_db_status());
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$statusGroup->get('/boost_status', function (Request $request, Response $response) {
$json = json_encode(get_boost_status());
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$statusGroup->get('/dsstats', function (Request $request, Response $response) {
$json = json_encode(get_dsstats_status());
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$statusGroup->get('/api_db_ping', function (Request $request, Response $response) {
$ping_result = db_fetch_row("SELECT 1 from version");
if (!$ping_result) {
$response->getBody()->write(json_encode(['error' => 'Database connection failed']));
return $response->withStatus(500)->withHeader('Content-Type', 'application/json');
}
$response->getBody()->write(json_encode(['status' => 'Database connection test successful']));
return $response->withHeader('Content-Type', 'application/json');
});
//automation status endpoint
$statusGroup->get('/automation', function (Request $request, Response $response) {
$json = json_encode(get_automation_status());
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
});
// Plugin endpoints
$group->group('/plugin', function (RouteCollectorProxy $pluginGroup) {
$pluginGroup->group('/thold', function (RouteCollectorProxy $tholdGroup) {
$tholdGroup->get('/thresholds', function (Request $request, Response $response) {
global $allowed_thold_filter, $client_ip;
$params = $request->getQueryParams();
$verror = validate_parameters($params, $allowed_thold_filter);
if ($verror) {
$response->getBody()->write(json_encode($verror));
cacti_log($verror . " By HOST: " . $client_ip, false, 'API');
return $response->withStatus(400)->withHeader('Content-Type', 'application/json');
}
$json = json_encode(get_thresholds($params));
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
$tholdGroup->get('/status', function (Request $request, Response $response) {
$json = json_encode(get_threshold_status());
$response->getBody()->write($json);
return $response->withHeader('Content-Type', 'application/json');
});
});
});
});
$app->run();