|
28 | 28 |
|
29 | 29 | use App\Facades\LibrenmsConfig; |
30 | 30 | use App\Models\Device; |
31 | | -use App\Models\DeviceOutage; |
32 | | -use App\Models\Eventlog; |
33 | | -use LibreNMS\Data\Source\Fping; |
34 | | -use LibreNMS\Data\Source\FpingResponse; |
35 | | -use LibreNMS\Enum\MaintenanceStatus; |
36 | | -use LibreNMS\Enum\Severity; |
37 | | -use SnmpQuery; |
38 | | -use Symfony\Component\Process\Process; |
39 | 31 |
|
40 | 32 | class ConnectivityHelper |
41 | 33 | { |
42 | | - /** |
43 | | - * @var Device |
44 | | - */ |
45 | | - private $device; |
46 | | - /** |
47 | | - * @var bool |
48 | | - */ |
49 | | - private $saveMetrics = false; |
50 | | - /** |
51 | | - * @var string |
52 | | - */ |
53 | | - private $family; |
54 | | - /** |
55 | | - * @var string |
56 | | - */ |
57 | | - private $target; |
58 | | - |
59 | | - public function __construct(Device $device) |
60 | | - { |
61 | | - $this->device = $device; |
62 | | - $this->target = $device->overwrite_ip ?: $device->hostname; |
63 | | - } |
64 | | - |
65 | | - /** |
66 | | - * After pinging the device, save metrics about the ping response |
67 | | - */ |
68 | | - public function saveMetrics(): void |
69 | | - { |
70 | | - $this->saveMetrics = true; |
71 | | - } |
72 | | - |
73 | | - /** |
74 | | - * Check if the device is up. |
75 | | - * Save availability and ping data if enabled with savePingPerf() |
76 | | - */ |
77 | | - public function isUp(): bool |
78 | | - { |
79 | | - $ping_response = $this->isPingable(); |
80 | | - |
81 | | - // calculate device status |
82 | | - if ($ping_response->success()) { |
83 | | - if (! $this->canSnmp() || $this->isSNMPable()) { |
84 | | - // up |
85 | | - $this->device->status = true; |
86 | | - $this->device->status_reason = ''; |
87 | | - } else { |
88 | | - // snmp down |
89 | | - $this->device->status = false; |
90 | | - $this->device->status_reason = 'snmp'; |
91 | | - } |
92 | | - } else { |
93 | | - // icmp down |
94 | | - $this->device->status = false; |
95 | | - $this->device->status_reason = 'icmp'; |
96 | | - } |
97 | | - |
98 | | - if ($this->saveMetrics) { |
99 | | - if ($this->canPing()) { |
100 | | - $ping_response->saveStats($this->device); |
101 | | - } |
102 | | - $this->updateAvailability($this->device->status); |
103 | | - |
104 | | - $this->device->save(); // confirm device is saved |
105 | | - } |
106 | | - |
107 | | - return $this->device->status; |
108 | | - } |
109 | | - |
110 | | - /** |
111 | | - * Check if the device responds to ICMP echo requests ("pings"). |
112 | | - */ |
113 | | - public function isPingable(): FpingResponse |
| 34 | + public static function snmpIsAllowed(Device $device): bool |
114 | 35 | { |
115 | | - if (! $this->canPing()) { |
116 | | - return FpingResponse::artificialUp($this->target); |
117 | | - } |
118 | | - |
119 | | - $status = app()->make(Fping::class)->ping($this->target, $this->ipFamily()); |
120 | | - |
121 | | - if ($status->duplicates > 0) { |
122 | | - Eventlog::log('Duplicate ICMP response detected! This could indicate a network issue.', $this->device, 'icmp', Severity::Warning); |
123 | | - $status->ignoreFailure(); // when duplicate is detected fping returns 1. The device is up, but there is another issue. Clue admins in with above event. |
124 | | - } |
125 | | - |
126 | | - return $status; |
| 36 | + return $device->snmp_disable === false; |
127 | 37 | } |
128 | 38 |
|
129 | | - public function isSNMPable(): bool |
| 39 | + public static function pingIsAllowed(Device $device): bool |
130 | 40 | { |
131 | | - $response = SnmpQuery::device($this->device)->get('SNMPv2-MIB::sysObjectID.0'); |
132 | | - |
133 | | - return $response->getExitCode() === 0 || $response->isValid(); |
134 | | - } |
135 | | - |
136 | | - public function traceroute(): array |
137 | | - { |
138 | | - $command = [LibrenmsConfig::get('traceroute', 'traceroute'), '-q', '1', '-w', '1', '-I', $this->target]; |
139 | | - if ($this->ipFamily() == 'ipv6') { |
140 | | - $command[] = '-6'; |
141 | | - } |
142 | | - |
143 | | - $process = new Process($command); |
144 | | - $process->setTimeout(120); |
145 | | - $process->run(); |
146 | | - |
147 | | - return [ |
148 | | - 'traceroute' => $process->getOutput(), |
149 | | - 'traceroute_output' => $process->getErrorOutput(), |
150 | | - ]; |
151 | | - } |
152 | | - |
153 | | - public function canSnmp(): bool |
154 | | - { |
155 | | - return ! $this->device->snmp_disable; |
156 | | - } |
157 | | - |
158 | | - public function canPing(): bool |
159 | | - { |
160 | | - return LibrenmsConfig::get('icmp_check') && ! ($this->device->exists && $this->device->getAttrib('override_icmp_disable') === 'true'); |
161 | | - } |
162 | | - |
163 | | - public function ipFamily(): string |
164 | | - { |
165 | | - if ($this->family === null) { |
166 | | - $this->family = preg_match('/6$/', $this->device->transport ?? '') ? 'ipv6' : 'ipv4'; |
167 | | - } |
168 | | - |
169 | | - return $this->family; |
170 | | - } |
171 | | - |
172 | | - private function updateAvailability(bool $current_status): void |
173 | | - { |
174 | | - // skip update if we are considering maintenance |
175 | | - if (LibrenmsConfig::get('graphing.availability_consider_maintenance') |
176 | | - && $this->device->getMaintenanceStatus() !== MaintenanceStatus::NONE) { |
177 | | - return; |
178 | | - } |
179 | | - |
180 | | - if ($current_status) { |
181 | | - // Device is up, close any open outages |
182 | | - $this->device->outages()->whereNull('up_again')->get()->each(function (DeviceOutage $outage) { |
183 | | - $outage->up_again = time(); |
184 | | - $outage->save(); |
185 | | - }); |
186 | | - |
187 | | - return; |
188 | | - } |
189 | | - |
190 | | - // Device is down, only open a new outage if none is currently open |
191 | | - if ($this->device->getCurrentOutage() === null) { |
192 | | - $this->device->outages()->save(new DeviceOutage(['going_down' => time()])); |
193 | | - } |
| 41 | + return LibrenmsConfig::get('icmp_check') && ! ($device->exists && $device->getAttrib('override_icmp_disable') === 'true'); |
194 | 42 | } |
195 | 43 | } |
0 commit comments