1<?php
2/**
3 * AvailabilityMapController.php
4 *
5 * -Description-
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 *
20 * @link       https://www.librenms.org
21 * @copyright  2018 Tony Murray
22 * @author     Tony Murray <murraytony@gmail.com>
23 */
24
25namespace App\Http\Controllers\Widgets;
26
27use App\Models\Device;
28use App\Models\DeviceGroup;
29use App\Models\Service;
30use Illuminate\Http\Request;
31use LibreNMS\Config;
32
33class AvailabilityMapController extends WidgetController
34{
35    protected $title = 'Availability Map';
36
37    public function __construct()
38    {
39        $this->defaults = [
40            'title' => null,
41            'type' => (int) Config::get('webui.availability_map_compact', 0),
42            'tile_size' => 12,
43            'color_only_select' => 0,
44            'show_disabled_and_ignored' => 0,
45            'mode_select' => 0,
46            'order_by' => Config::get('webui.availability_map_sort_status') ? 'status' : 'hostname',
47            'device_group' => null,
48        ];
49    }
50
51    public function getView(Request $request)
52    {
53        $data = $this->getSettings();
54
55        $devices = [];
56        $device_totals = [];
57        $services = [];
58        $services_totals = [];
59
60        $mode = $data['mode_select'];
61        if ($mode == 0 || $mode == 2) {
62            [$devices, $device_totals] = $this->getDevices($request);
63        }
64        if ($mode > 0) {
65            [$services, $services_totals] = $this->getServices($request);
66        }
67
68        $data['device'] = Device::first();
69
70        $data['devices'] = $devices;
71        $data['device_totals'] = $device_totals;
72        $data['services'] = $services;
73        $data['services_totals'] = $services_totals;
74
75        return view('widgets.availability-map', $data);
76    }
77
78    public function getSettingsView(Request $request)
79    {
80        return view('widgets.settings.availability-map', $this->getSettings(true));
81    }
82
83    /**
84     * @param Request $request
85     * @return array
86     */
87    private function getDevices(Request $request)
88    {
89        $settings = $this->getSettings();
90
91        // filter for by device group or show all
92        if ($settings['device_group']) {
93            $device_query = DeviceGroup::find($settings['device_group'])->devices()->hasAccess($request->user());
94        } else {
95            $device_query = Device::hasAccess($request->user());
96        }
97
98        if (! $settings['show_disabled_and_ignored']) {
99            $device_query->isNotDisabled();
100        }
101        $device_query->orderBy($settings['order_by']);
102        $devices = $device_query->select('devices.device_id', 'hostname', 'sysName', 'status', 'uptime', 'last_polled', 'disabled', 'disable_notify', 'location_id')->get();
103
104        // process status
105        $uptime_warn = Config::get('uptime_warning', 84600);
106        $totals = ['warn' => 0, 'up' => 0, 'down' => 0, 'maintenance' => 0, 'ignored' => 0, 'disabled' => 0];
107        foreach ($devices as $device) {
108            if ($device->disabled) {
109                $totals['disabled']++;
110                $device->stateName = 'disabled';
111                $device->labelClass = 'blackbg';
112            } elseif ($device->disable_notify) {
113                $totals['ignored']++;
114                $device->stateName = 'alert-dis';
115                $device->labelClass = 'label-default';
116            } elseif ($device->status == 1) {
117                if (($device->uptime < $uptime_warn) && ($device->uptime != 0)) {
118                    $totals['warn']++;
119                    $device->stateName = 'warn';
120                    $device->labelClass = 'label-warning';
121                } else {
122                    $totals['up']++;
123                    $device->stateName = 'up';
124                    $device->labelClass = 'label-success';
125                }
126            } else {
127                $totals['down']++;
128                $device->stateName = 'down';
129                $device->labelClass = 'label-danger';
130            }
131
132            if ($device->isUnderMaintenance()) {
133                $device->labelClass = 'label-default';
134                $totals['maintenance']++;
135            }
136        }
137
138        return [$devices, $totals];
139    }
140
141    private function getServices($request)
142    {
143        $settings = $this->getSettings();
144
145        // filter for by device group or show all
146        if ($settings['device_group']) {
147            $services_query = DeviceGroup::find($settings['device_group'])->services()->hasAccess($request->user());
148        } else {
149            $services_query = Service::hasAccess($request->user());
150        }
151
152        if ($settings['order_by'] == 'status') {
153            $services_query->orderBy('service_status', 'DESC')->orderBy('service_type');
154        } elseif ($settings['order_by'] == 'hostname') {
155            $services_query->leftJoin('devices', 'services.device_id', 'devices.device_id')->orderBy('hostname')->orderBy('service_type');
156        }
157        $services = $services_query->with(['device' => function ($query) {
158            $query->select('devices.device_id', 'hostname', 'sysName');
159        }])->select('service_id', 'services.device_id', 'service_type', 'service_desc', 'service_status')->get();
160
161        // process status
162        $totals = ['warn' => 0, 'up' => 0, 'down' => 0];
163        foreach ($services as $service) {
164            if ($service->service_status == 0) {
165                $service->labelClass = 'label-success';
166                $service->stateName = 'up';
167                $totals['up']++;
168            } elseif ($service->service_status == 1) {
169                $service->labelClass = 'label-warning';
170                $service->stateName = 'warn';
171                $totals['warn']++;
172            } else {
173                $service->labelClass = 'label-danger';
174                $service->stateName = 'down';
175                $totals['down']++;
176            }
177        }
178
179        return [$services, $totals];
180    }
181}
182