From 62b4c21a1233dd8ebe71a84efe7338c30a535ac6 Mon Sep 17 00:00:00 2001 From: laf Date: Sat, 12 Dec 2015 12:58:07 +0000 Subject: [PATCH 1/4] Added API calls for device groups --- doc/API/API-Docs.md | 73 +++++++++++++++++++++++++++++ html/api_v0.php | 2 + html/includes/api_functions.inc.php | 36 +++++++++++++- includes/device-groups.inc.php | 18 ++++++- 4 files changed, 127 insertions(+), 2 deletions(-) diff --git a/doc/API/API-Docs.md b/doc/API/API-Docs.md index e879fe637b..c9dd5c99ec 100644 --- a/doc/API/API-Docs.md +++ b/doc/API/API-Docs.md @@ -19,6 +19,9 @@ - [`add_device`](#api-route-11) - [`list_oxidized`](#api-route-21) - [`update_device_field`](#api-route-update_device_field) + - [`get_device_groups`](#api-route-get_device_groups) + - [`devicegroups`](#api-devicegroups) + - [`get_devicegroups`](#api-route-get_devicegroups) - [`routing`](#api-routing) - [`list_bgp`](#api-route-1) - [`switching`](#api-switching) @@ -490,6 +493,76 @@ Output: ] ``` +### Function `get_device_groups` [`top`](#top) + +List the device groups that a device is matched on. + +Route: /api/v0/devices/:hostname/groups + +Input (JSON): + + - + +Examples: +```curl +curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/localhost/groups +``` + +Output: +```text +[ + { + "status": "ok", + "message": "Found 1 device groups", + "count": 1, + "groups": [ + { + "id": "1", + "name": "Testing", + "desc": "Testing", + "pattern": "%devices.status = \"1\" &&" + } + ] + } +] +``` + +## `Device Groups` [`top`](#top) + +### Function `get_devicegroups` [`top`](#top) + +List all device groups. + +Route: /api/v0/devicegroups + +Input (JSON): + + - + +Examples: +```curl +curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devicegroups +``` + +Output: +```text +[ + { + "status": "ok", + "message": "Found 1 device groups", + "count": 1, + "groups": [ + { + "id": "1", + "name": "Testing", + "desc": "Testing", + "pattern": "%devices.status = \"1\" &&" + } + ] + } +] +``` + ## `Routing` [`top`](#top) ### Function: `list_bgp` [`top`](#top) diff --git a/html/api_v0.php b/html/api_v0.php index 426591162b..d5de47c5ee 100644 --- a/html/api_v0.php +++ b/html/api_v0.php @@ -49,6 +49,7 @@ $app->group( // api/v0/devices/$hostname/graphs $app->get('/:hostname/ports', 'authToken', 'get_port_graphs')->name('get_port_graphs'); // api/v0/devices/$hostname/ports + $app->get('/:hostname/groups', 'authToken', 'get_device_groups')->name('get_device_groups'); $app->get('/:hostname/:type', 'authToken', 'get_graph_generic_by_hostname')->name('get_graph_generic_by_hostname'); // api/v0/devices/$hostname/$type $app->get('/:hostname/ports/:ifname', 'authToken', 'get_port_stats_by_port_hostname')->name('get_port_stats_by_port_hostname'); @@ -61,6 +62,7 @@ $app->group( // api/v0/devices $app->post('/devices', 'authToken', 'add_device')->name('add_device'); // api/v0/devices (json data needs to be passed) + $app->get('/devicegroups', 'authToken', 'get_device_groups')->name('get_devicegroups'); $app->group( '/portgroups', function () use ($app) { diff --git a/html/includes/api_functions.inc.php b/html/includes/api_functions.inc.php index 8469e10532..de6c307c36 100644 --- a/html/includes/api_functions.inc.php +++ b/html/includes/api_functions.inc.php @@ -13,7 +13,7 @@ */ require_once '../includes/functions.php'; - +require_once '../includes/device-groups.inc.php'; function authToken(\Slim\Route $route) { $app = \Slim\Slim::getInstance(); @@ -1014,3 +1014,37 @@ function update_device() { $app->response->headers->set('Content-Type', 'application/json'); echo _json_encode($output); } + +function get_device_groups() { + $app = \Slim\Slim::getInstance(); + $router = $app->router()->getCurrentRoute()->getParams(); + $status = 'error'; + $code = 404; + $hostname = $router['hostname']; + // use hostname as device_id if it's all digits + $device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname); + if (is_numeric($device_id)) { + $groups = GetFullGroupsFromDevice($device_id); + } + else { + $groups = GetDeviceGroups(); + } + if (empty($groups)) { + $message = 'No device groups found'; + } + else { + $status = 'ok'; + $code = 200; + $message = 'Found ' . count($groups) . ' device groups'; + } + + $output = array( + 'status' => $status, + 'message' => $message, + 'count' => count($groups), + 'groups' => $groups, + ); + $app->response->setStatus($code); + $app->response->headers->set('Content-Type', 'application/json'); + echo _json_encode($output); +} diff --git a/includes/device-groups.inc.php b/includes/device-groups.inc.php index 45d5afcd21..6f81048463 100644 --- a/includes/device-groups.inc.php +++ b/includes/device-groups.inc.php @@ -99,7 +99,6 @@ function GetDeviceGroups() { }//end GetDeviceGroups() - /** * Get all groups of Device * @param integer $device Device-ID @@ -117,6 +116,23 @@ function GetGroupsFromDevice($device) { }//end GetGroupsFromDevice() +/** + * Get all groups of Device + * @param integer $device Device-ID + * @return array + */ +function GetFullGroupsFromDevice($device) { + $ret = array(); + foreach (GetDeviceGroups() as $group) { + if (dbFetchCell(GenGroupSQL($group['pattern'], 'device_id=?').' LIMIT 1', array($device)) == $device) { + $ret[] = $group; + } + } + + return $ret; + +}//end GetGroupsFromDevice() + /** * Process Macros * @param string $rule Rule to process From a73a997edc843b47277f0c3f365bd6199730705b Mon Sep 17 00:00:00 2001 From: laf Date: Sat, 12 Dec 2015 13:47:44 +0000 Subject: [PATCH 2/4] Added API call for listing devices by groups --- doc/API/API-Docs.md | 81 +++++++++++++++++++++++++++++ html/api_v0.php | 6 +++ html/includes/api_functions.inc.php | 35 +++++++++++++ includes/device-groups.inc.php | 2 +- 4 files changed, 123 insertions(+), 1 deletion(-) diff --git a/doc/API/API-Docs.md b/doc/API/API-Docs.md index c9dd5c99ec..3e96ebe703 100644 --- a/doc/API/API-Docs.md +++ b/doc/API/API-Docs.md @@ -22,6 +22,7 @@ - [`get_device_groups`](#api-route-get_device_groups) - [`devicegroups`](#api-devicegroups) - [`get_devicegroups`](#api-route-get_devicegroups) + - [`get_devices_by_group`](#api-route-get_devices_by_group) - [`routing`](#api-routing) - [`list_bgp`](#api-route-1) - [`switching`](#api-switching) @@ -472,6 +473,8 @@ Update devices field in the database. Route: /api/v0/devices/:hostname +- hostname can be either the device hostname or id + Input (JSON): - field: The column name within the database @@ -499,6 +502,8 @@ List the device groups that a device is matched on. Route: /api/v0/devices/:hostname/groups +- hostname can be either the device hostname or id + Input (JSON): - @@ -563,6 +568,82 @@ Output: ] ``` +### Function `get_devices_by_group` [`top`](#top) + +List all devices matching the group provided. + +Route: /api/v0/devicegroups/:name + +- name Is the name of the device group which can be obtained using [`get_devicegroups`](#api-route-get_devicegroups). Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. + +Input (JSON): + + - + +Examples: +```curl +curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devicegroups/LinuxServers +``` + +Output: +```text +[ + { + "status": "error", + "message": "Found 1 in group LinuxServers", + "count": 1, + "devices": [ + { + "device_id": "1", + "hostname": "localhost", + "sysName": "hostname", + "community": "librenms", + "authlevel": null, + "authname": null, + "authpass": null, + "authalgo": null, + "cryptopass": null, + "cryptoalgo": null, + "snmpver": "v2c", + "port": "161", + "transport": "udp", + "timeout": null, + "retries": null, + "bgpLocalAs": null, + "sysObjectID": ".1.3.6.1.4.1.8072.3.2.10", + "sysDescr": "Linux li1045-133.members.linode.com 4.1.5-x86_64-linode61 #7 SMP Mon Aug 24 13:46:31 EDT 2015 x86_64", + "sysContact": "", + "version": "4.1.5-x86_64-linode61", + "hardware": "Generic x86 64-bit", + "features": "CentOS 7.1.1503", + "location": "", + "os": "linux", + "status": "1", + "status_reason": "", + "ignore": "0", + "disabled": "0", + "uptime": "4615964", + "agent_uptime": "0", + "last_polled": "2015-12-12 13:20:04", + "last_poll_attempted": null, + "last_polled_timetaken": "1.90", + "last_discovered_timetaken": "79.53", + "last_discovered": "2015-12-12 12:34:21", + "last_ping": "2015-12-12 13:20:04", + "last_ping_timetaken": "0.08", + "purpose": null, + "type": "server", + "serial": null, + "icon": null, + "poller_group": "0", + "override_sysLocation": "0", + "notes": "Nope" + } + ] + } +] +``` + ## `Routing` [`top`](#top) ### Function: `list_bgp` [`top`](#top) diff --git a/html/api_v0.php b/html/api_v0.php index d5de47c5ee..e46c0a3ea8 100644 --- a/html/api_v0.php +++ b/html/api_v0.php @@ -62,6 +62,12 @@ $app->group( // api/v0/devices $app->post('/devices', 'authToken', 'add_device')->name('add_device'); // api/v0/devices (json data needs to be passed) + $app->group( + '/devicegroups', + function () use ($app) { + $app->get('/:name', 'authToken', 'get_devices_by_group')->name('get_devices_by_group'); + } + ); $app->get('/devicegroups', 'authToken', 'get_device_groups')->name('get_devicegroups'); $app->group( '/portgroups', diff --git a/html/includes/api_functions.inc.php b/html/includes/api_functions.inc.php index de6c307c36..7f89b37cb1 100644 --- a/html/includes/api_functions.inc.php +++ b/html/includes/api_functions.inc.php @@ -1048,3 +1048,38 @@ function get_device_groups() { $app->response->headers->set('Content-Type', 'application/json'); echo _json_encode($output); } + +function get_devices_by_group() { + $app = \Slim\Slim::getInstance(); + $router = $app->router()->getCurrentRoute()->getParams(); + $status = 'error'; + $code = 404; + $name = urldecode($router['name']); + $devices = array(); + if (empty($name)) { + $message = 'No device group name provided'; + } + else { + $group_id = dbFetchCell("SELECT `id` FROM `device_groups` WHERE `name`=?",array($name)); + $devices = GetDevicesFromGroup($group_id); + $count = count($devices); + if (empty($devices)) { + $message = 'No devices found in group ' . $name; + } + else { + $message = "Found $count in group $name"; + $code = 200; + } + } + $output = array( + 'status' => $status, + 'message' => $message, + 'count' => $count, + 'devices' => $devices, + ); + + $app->response->setStatus($code); + $app->response->headers->set('Content-Type', 'application/json'); + echo _json_encode($output); + +} diff --git a/includes/device-groups.inc.php b/includes/device-groups.inc.php index 6f81048463..bb703f2cd6 100644 --- a/includes/device-groups.inc.php +++ b/includes/device-groups.inc.php @@ -66,7 +66,7 @@ function GenGroupSQL($pattern, $search='') { $search .= ' &&'; } - $sql = 'SELECT DISTINCT('.str_replace('(', '', $tables[0]).'.device_id) FROM '.implode(',', $tables).' WHERE '.$search.' ('.str_replace(array('%', '@', '!~', '~'), array('', '.*', 'NOT REGEXP', 'REGEXP'), $pattern).')'; + $sql = 'SELECT DISTINCT('.str_replace('(', '', $tables[0]).'.device_id),`devices`.* FROM '.implode(',', $tables).' WHERE '.$search.' ('.str_replace(array('%', '@', '!~', '~'), array('', '.*', 'NOT REGEXP', 'REGEXP'), $pattern).')'; return $sql; }//end GenGroupSQL() From d0306ae8ae630b1cc9968e832cb2a59ac2d451ef Mon Sep 17 00:00:00 2001 From: laf Date: Sat, 12 Dec 2015 14:21:49 +0000 Subject: [PATCH 3/4] Fixing scrut issue --- html/includes/api_functions.inc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/html/includes/api_functions.inc.php b/html/includes/api_functions.inc.php index 7f89b37cb1..a6ca257235 100644 --- a/html/includes/api_functions.inc.php +++ b/html/includes/api_functions.inc.php @@ -1054,6 +1054,7 @@ function get_devices_by_group() { $router = $app->router()->getCurrentRoute()->getParams(); $status = 'error'; $code = 404; + $count = 0; $name = urldecode($router['name']); $devices = array(); if (empty($name)) { From d5b6e0e8da2440e5f9bf92ca9f08c02d7e662e16 Mon Sep 17 00:00:00 2001 From: laf Date: Sun, 13 Dec 2015 17:20:34 +0000 Subject: [PATCH 4/4] Updated device-groups functions to support returning all data or just group id --- html/includes/api_functions.inc.php | 2 +- includes/device-groups.inc.php | 36 +++++++++++------------------ 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/html/includes/api_functions.inc.php b/html/includes/api_functions.inc.php index a6ca257235..5a0cead146 100644 --- a/html/includes/api_functions.inc.php +++ b/html/includes/api_functions.inc.php @@ -1024,7 +1024,7 @@ function get_device_groups() { // use hostname as device_id if it's all digits $device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname); if (is_numeric($device_id)) { - $groups = GetFullGroupsFromDevice($device_id); + $groups = GetGroupsFromDevice($device_id,1); } else { $groups = GetDeviceGroups(); diff --git a/includes/device-groups.inc.php b/includes/device-groups.inc.php index bb703f2cd6..3624db490c 100644 --- a/includes/device-groups.inc.php +++ b/includes/device-groups.inc.php @@ -31,7 +31,7 @@ * @param string $search What to searchid for * @return string */ -function GenGroupSQL($pattern, $search='') { +function GenGroupSQL($pattern, $search='',$extra=0) { $pattern = RunGroupMacros($pattern); if ($pattern === false) { return false; @@ -66,7 +66,11 @@ function GenGroupSQL($pattern, $search='') { $search .= ' &&'; } - $sql = 'SELECT DISTINCT('.str_replace('(', '', $tables[0]).'.device_id),`devices`.* FROM '.implode(',', $tables).' WHERE '.$search.' ('.str_replace(array('%', '@', '!~', '~'), array('', '.*', 'NOT REGEXP', 'REGEXP'), $pattern).')'; + $sql_extra = ''; + if ($extra === 1) { + $sql_extra = ",`devices`.*"; + } + $sql = 'SELECT DISTINCT('.str_replace('(', '', $tables[0]).'.device_id)'.$sql_extra.' FROM '.implode(',', $tables).' WHERE '.$search.' ('.str_replace(array('%', '@', '!~', '~'), array('', '.*', 'NOT REGEXP', 'REGEXP'), $pattern).')'; return $sql; }//end GenGroupSQL() @@ -104,28 +108,16 @@ function GetDeviceGroups() { * @param integer $device Device-ID * @return array */ -function GetGroupsFromDevice($device) { +function GetGroupsFromDevice($device,$extra=0) { $ret = array(); foreach (GetDeviceGroups() as $group) { - if (dbFetchCell(GenGroupSQL($group['pattern'], 'device_id=?').' LIMIT 1', array($device)) == $device) { - $ret[] = $group['id']; - } - } - - return $ret; - -}//end GetGroupsFromDevice() - -/** - * Get all groups of Device - * @param integer $device Device-ID - * @return array - */ -function GetFullGroupsFromDevice($device) { - $ret = array(); - foreach (GetDeviceGroups() as $group) { - if (dbFetchCell(GenGroupSQL($group['pattern'], 'device_id=?').' LIMIT 1', array($device)) == $device) { - $ret[] = $group; + if (dbFetchCell(GenGroupSQL($group['pattern'], 'device_id=?',$extra).' LIMIT 1', array($device)) == $device) { + if ($extra === 0) { + $ret[] = $group['id']; + } + else { + $ret[] = $group; + } } }