Geographical map: Show network links between locations (#11269)

* Geographical map: Show links between locations

* Fix manifest after merge conflict
This commit is contained in:
Mathieu Poussin
2020-03-13 11:22:32 +01:00
committed by GitHub
parent 2ee2862357
commit 1cf7e206e5
4 changed files with 136 additions and 7 deletions

View File

@@ -3,10 +3,10 @@
"/css/app.css": "/css/app.css?id=2a88c6515df894dc6f36", "/css/app.css": "/css/app.css?id=2a88c6515df894dc6f36",
"/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e", "/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e",
"/js/vendor.js": "/js/vendor.js?id=58c8fc0774b5843ec004", "/js/vendor.js": "/js/vendor.js?id=58c8fc0774b5843ec004",
"/js/lang/de.js": "/js/lang/de.js?id=e0623715e8df0895188b", "/js/lang/de.js": "/js/lang/de.js?id=8c1c390a5f45ac01d54b",
"/js/lang/en.js": "/js/lang/en.js?id=ad9c97639001057c62d7", "/js/lang/en.js": "/js/lang/en.js?id=201d470a19d7fa80027b",
"/js/lang/fr.js": "/js/lang/fr.js?id=2d1159debd99a1909f12", "/js/lang/fr.js": "/js/lang/fr.js?id=807a43a37f4eeb4c1d17",
"/js/lang/ru.js": "/js/lang/ru.js?id=b007ddce75134acbe635", "/js/lang/ru.js": "/js/lang/ru.js?id=1a4435677a27aa615af1",
"/js/lang/uk.js": "/js/lang/uk.js?id=146819d3cf1dfb16672d", "/js/lang/uk.js": "/js/lang/uk.js?id=6ce358a9e9387947ee03",
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=e578b34b9d5e21cf929d" "/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=3ad4a3e6a5a59165e806"
} }

View File

@@ -130,6 +130,123 @@ var marker = L.marker(new L.LatLng(".$map_devices['lat'].", ".$map_devices['lng'
marker.bindPopup(title); marker.bindPopup(title);
markers.addLayer(marker);\n"; markers.addLayer(marker);\n";
} }
if (Config::get('network_map_show_on_worldmap')) {
if (Auth::user()->hasGlobalRead()) {
$sql = "
SELECT
ll.id AS left_id,
ll.lat AS left_lat,
ll.lng AS left_lng,
rl.id AS right_id,
rl.lat AS right_lat,
rl.lng AS right_lng,
sum(lp.ifHighSpeed) AS link_capacity,
sum(lp.ifOutOctets_rate) * 8 / sum(lp.ifSpeed) * 100 as link_out_usage_pct,
sum(lp.ifInOctets_rate) * 8 / sum(lp.ifSpeed) * 100 as link_in_usage_pct
FROM
devices AS ld,
devices AS rd,
links AS l,
locations AS ll,
locations AS rl,
ports as lp
WHERE
l.local_device_id = ld.device_id
AND l.remote_device_id = rd.device_id
AND ld.location_id != rd.location_id
AND ld.location_id = ll.id
AND rd.location_id = rl.id
AND lp.device_id = ld.device_id
AND lp.port_id = l.local_port_id
AND lp.ifType = 'ethernetCsmacd'
AND ld.disabled = 0
AND ld.ignore = 0
AND rd.disabled = 0
AND rd.ignore = 0
AND ld.status IN " . dbGenPlaceholders(count($show_status)) . "
AND rd.status IN " . dbGenPlaceholders(count($show_status)) . "
GROUP BY
left_id, right_id, ll.lat, ll.lng, rl.lat, rl.lng
";
$param = array_merge($show_status, $show_status);
} else {
$device_ids = Permissions::devicesForUser()->toArray() ?: [0];
$sql = "
SELECT
ll.id AS left_id,
ll.lat AS left_lat,
ll.lng AS left_lng,
rl.id AS right_id,
rl.lat AS right_lat,
rl.lng AS right_lng,
sum(lp.ifHighSpeed) AS link_capacity,
sum(lp.ifOutOctets_rate) * 8 / sum(lp.ifSpeed) * 100 as link_out_usage_pct,
sum(lp.ifInOctets_rate) * 8 / sum(lp.ifSpeed) * 100 as link_in_usage_pct
FROM
devices AS ld,
devices AS rd,
links AS l,
locations AS ll,
locations AS rl,
ports as lp
WHERE
l.local_device_id = ld.device_id
AND l.remote_device_id = rd.device_id
AND ld.location_id != rd.location_id
AND ld.location_id = ll.id
AND rd.location_id = rl.id
AND lp.device_id = ld.device_id
AND lp.port_id = l.local_port_id
AND lp.ifType = 'ethernetCsmacd'
AND ld.disabled = 0
AND ld.ignore = 0
AND rd.disabled = 0
AND rd.ignore = 0
AND ld.status IN " . dbGenPlaceholders(count($show_status)) . "
AND rd.status IN " . dbGenPlaceholders(count($show_status)) . "
AND ld.device_id IN " . dbGenPlaceholders(count($device_ids)) . "
AND rd.device_id IN " . dbGenPlaceholders(count($device_ids)) . "
GROUP BY
left_id, right_id, ll.lat, ll.lng, rl.lat, rl.lng
";
$param = array_merge($show_status, $show_status, $device_ids, $device_ids);
}
foreach (dbFetchRows($sql, $param) as $link) {
$icon = 'greenMarker';
$z_offset = 0;
$speed = $link['link_capacity']/1000;
if ($speed > 500000) {
$width = 20;
} else {
$width = round(0.77 * pow($speed, 0.25));
}
$link_used = ($link["link_out_usage_pct"] + $link["link_in_usage_pct"]) / 2;
$link_used = round(2 * $link_used, -1) / 2;
if ($link_used > 100) {
$link_used = 100;
}
if (is_nan($link_used)) {
$link_used = 0;
}
$link_color = Config::get("network_map_legend.$link_used");
$temp_output .= "var marker = new L.Polyline([new L.LatLng(". $link["left_lat"] .", ". $link["left_lng"] ."), new L.LatLng(". $link["right_lat"] .", ". $link["right_lng"] .")], {
color: '". $link_color ."',
weight: ". $width .",
opacity: 0.8,
smoothFactor: 1
});
markers.addLayer(marker);
";
}
}
$temp_output .= 'map.addLayer(markers); $temp_output .= 'map.addLayer(markers);
map.scrollWheelZoom.disable(); map.scrollWheelZoom.disable();
$(document).ready(function(){ $(document).ready(function(){

View File

@@ -3649,6 +3649,13 @@
}, },
"type": "array" "type": "array"
}, },
"network_map_show_on_worldmap": {
"default": false,
"type": "boolean",
"group": "webui",
"section": "worldmap",
"order": 1
},
"network_map_vis_options": { "network_map_vis_options": {
"default": "{\n layout:{\n randomSeed:2\n },\n \"edges\": {\n arrows: {\n to: {enabled: true, scaleFactor:0.5},\n },\n \"smooth\": {\n enabled: false\n },\n font: {\n size: 14,\n color: \"red\",\n face: \"sans\",\n background: \"white\",\n strokeWidth:3,\n align: \"middle\",\n strokeWidth: 2\n }\n },\n \"physics\": {\n \"barnesHut\": {\n \"gravitationalConstant\": -2000,\n \"centralGravity\": 0.3,\n \"springLength\": 200,\n \"springConstant\": 0.04,\n \"damping\": 0.09,\n \"avoidOverlap\": 1\n },\n\n \"forceAtlas2Based\": {\n \"gravitationalConstant\": -50,\n \"centralGravity\": 0.01,\n \"springLength\": 200,\n \"springConstant\": 0.08,\n \"damping\": 0.4,\n \"avoidOverlap\": 1\n },\n\n \"repulsion\": {\n \"centralGravity\": 0.2,\n \"springLength\": 250,\n \"springConstant\": 0.2,\n \"nodeDistance\": 200,\n \"damping\": 0.07\n },\n\n \"hierarchicalRepulsion\": {\n \"nodeDistance\": 300,\n \"centralGravity\": 0.2,\n \"springLength\": 300,\n \"springConstant\": 0.2,\n \"damping\": 0.07\n },\n\n \"maxVelocity\": 50,\n \"minVelocity\": 0.4,\n \"solver\": \"hierarchicalRepulsion\",\n \"stabilization\": {\n \"enabled\": true,\n \"iterations\": 1000,\n \"updateInterval\": 100,\n \"onlyDynamicEdges\": false,\n \"fit\": true\n },\n\n \"timestep\": 0.4,\n }\n}", "default": "{\n layout:{\n randomSeed:2\n },\n \"edges\": {\n arrows: {\n to: {enabled: true, scaleFactor:0.5},\n },\n \"smooth\": {\n enabled: false\n },\n font: {\n size: 14,\n color: \"red\",\n face: \"sans\",\n background: \"white\",\n strokeWidth:3,\n align: \"middle\",\n strokeWidth: 2\n }\n },\n \"physics\": {\n \"barnesHut\": {\n \"gravitationalConstant\": -2000,\n \"centralGravity\": 0.3,\n \"springLength\": 200,\n \"springConstant\": 0.04,\n \"damping\": 0.09,\n \"avoidOverlap\": 1\n },\n\n \"forceAtlas2Based\": {\n \"gravitationalConstant\": -50,\n \"centralGravity\": 0.01,\n \"springLength\": 200,\n \"springConstant\": 0.08,\n \"damping\": 0.4,\n \"avoidOverlap\": 1\n },\n\n \"repulsion\": {\n \"centralGravity\": 0.2,\n \"springLength\": 250,\n \"springConstant\": 0.2,\n \"nodeDistance\": 200,\n \"damping\": 0.07\n },\n\n \"hierarchicalRepulsion\": {\n \"nodeDistance\": 300,\n \"centralGravity\": 0.2,\n \"springLength\": 300,\n \"springConstant\": 0.2,\n \"damping\": 0.07\n },\n\n \"maxVelocity\": 50,\n \"minVelocity\": 0.4,\n \"solver\": \"hierarchicalRepulsion\",\n \"stabilization\": {\n \"enabled\": true,\n \"iterations\": 1000,\n \"updateInterval\": 100,\n \"onlyDynamicEdges\": false,\n \"fit\": true\n },\n\n \"timestep\": 0.4,\n }\n}",
"type": "text" "type": "text"

View File

@@ -67,6 +67,7 @@ return [
'search' => 'Search Settings', 'search' => 'Search Settings',
'style' => 'Style', 'style' => 'Style',
'device' => 'Device Settings', 'device' => 'Device Settings',
'worldmap' => 'World Map Settings'
] ]
], ],
'settings' => [ 'settings' => [
@@ -761,6 +762,10 @@ return [
'description' => 'Primary Domain', 'description' => 'Primary Domain',
'help' => 'This domain is used for network auto-discovery and other processes. LibreNMS will attempt to append it to unqualified hostnames.' 'help' => 'This domain is used for network auto-discovery and other processes. LibreNMS will attempt to append it to unqualified hostnames.'
], ],
'network_map_show_on_worldmap' => [
'description' => 'Display network links on the map',
'help' => 'Show the networks links between the different location on the worldmap (weathermap-like)'
],
'nfsen_enable' => [ 'nfsen_enable' => [
'description' => 'Enable NfSen', 'description' => 'Enable NfSen',
'help' => 'Enable Integration with NfSen', 'help' => 'Enable Integration with NfSen',