Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- System-wide default welcome message ([#3301])
- Privacy setting to disable finding users by partial matches of their name or email address ([#2264], [#3316])
- Hints in admin UI file uploads indicating supported file types and maximum allowed file size ([#3235])
- Option to set connection status of servers to always online ([#3317], [#3373])

### Changed

- Allow SVG and WebP images to be used as livestream pause images ([#3235])
- Accessibility: aria-labels for filter and sort select elements in room tabs ([#3298])
- Accessibility: Updated aria-label values for buttons and select controls to provide more descriptive context ([#3241], [#3242])
- Prometheus metric label `pilos_servers_total{status="unhealthy"}` to `pilos_servers_total{status="faulty"}` ([#3373])
- Connection status terminology in log messages (`unhealthy` to `faulty`; `healthy` to `online`; `old_health` to `old_connection_status`) ([#3373])

### Fixed

Expand Down Expand Up @@ -888,6 +891,8 @@ You can find the changelog for older versions there [here](https://github.com/TH
[#3314]: https://github.com/THM-Health/PILOS/issues/3314
[#3315]: https://github.com/THM-Health/PILOS/pull/3315
[#3316]: https://github.com/THM-Health/PILOS/pull/3316
[#3317]: https://github.com/THM-Health/PILOS/issues/3317
[#3373]: https://github.com/THM-Health/PILOS/pull/3373
[unreleased]: https://github.com/THM-Health/PILOS/compare/v4.17.0...develop
[v3.0.0]: https://github.com/THM-Health/PILOS/releases/tag/v3.0.0
[v3.0.1]: https://github.com/THM-Health/PILOS/releases/tag/v3.0.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@

namespace App\Enums;

/**
* Custom status response codes of the api
*/
enum ServerHealth: int
enum ServerConnectionStatus: int
{
case ONLINE = 1;
case UNHEALTHY = 0;
case FAULTY = 0;
case OFFLINE = -1;
}
3 changes: 0 additions & 3 deletions app/Enums/ServerStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

namespace App\Enums;

/**
* Custom status response codes of the api
*/
enum ServerStatus: int
{
case DISABLED = -1;
Expand Down
4 changes: 3 additions & 1 deletion app/Http/Controllers/api/v1/ServerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,12 @@ public function update(ServerRequest $request, Server $server)
$server->secret = $request->secret;
$server->strength = $request->strength;
$server->status = $request->status;
$server->connection_status_always_online = $request->boolean('connection_status_always_online');

$server->error_count = 0;
$server->recover_count = config('bigbluebutton.server_online_threshold');

// Check if server is online/offline and update usage data
// Update server usage, load data and connection status
$serverService = new ServerService($server);
$serverService->updateUsage();

Expand All @@ -134,6 +135,7 @@ public function store(ServerRequest $request)
$server->secret = $request->secret;
$server->strength = $request->strength;
$server->status = $request->status;
$server->connection_status_always_online = $request->boolean('connection_status_always_online');

$server->error_count = 0;
$server->recover_count = config('bigbluebutton.server_online_threshold');
Expand Down
1 change: 1 addition & 0 deletions app/Http/Requests/ServerRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function rules()
'secret' => ['required', 'string', 'max:255'],
'strength' => ['required', 'integer', 'min:1', 'max:10'],
'status' => ['required', Rule::enum(ServerStatus::class)],
'connection_status_always_online' => ['required', 'boolean'],
Comment thread
samuelwei marked this conversation as resolved.
];

if ($this->route('server')) {
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Resources/ServerResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ public function toArray($request)
'name' => $this->name,
'description' => $this->description,
'strength' => $this->strength,
'connection_status_always_online' => $this->connection_status_always_online,
'status' => $this->status,
'health' => $this->health,
'connection_status' => $this->connection_status,
'participant_count' => $this->participant_count,
'listener_count' => $this->listener_count,
'voice_participant_count' => $this->voice_participant_count,
Expand Down
21 changes: 14 additions & 7 deletions app/Models/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace App\Models;

use App\Enums\ServerHealth;
use App\Enums\ServerConnectionStatus;
use App\Enums\ServerStatus;
use App\Observers\ServerObserver;
use App\Traits\AddsModelNameTrait;
Expand All @@ -22,6 +22,7 @@ class Server extends Model

protected $casts = [
'strength' => 'integer',
'connection_status_always_online' => 'boolean',
'status' => ServerStatus::class,
'participant_count' => 'integer',
'listener_count' => 'integer',
Expand Down Expand Up @@ -78,24 +79,30 @@ public function getLogLabel()
return $this->name.' ('.$this->id.')';
}

public function getHealthAttribute(): ?ServerHealth
public function getConnectionStatusAttribute(): ?ServerConnectionStatus
{
// No connection status available for disabled servers
if ($this->status == ServerStatus::DISABLED) {
return null;
}

return self::calcHealth($this->recover_count, $this->error_count);
// Always return online if connection_status_always_online
if ($this->connection_status_always_online) {
return ServerConnectionStatus::ONLINE;
}

return self::calculateConnectionStatus($this->recover_count, $this->error_count);
}

public static function calcHealth(int $recover_count, int $error_count): ServerHealth
public static function calculateConnectionStatus(int $recover_count, int $error_count): ServerConnectionStatus
{
if ($recover_count >= config('bigbluebutton.server_online_threshold')) {
return ServerHealth::ONLINE;
return ServerConnectionStatus::ONLINE;
}
if ($error_count >= config('bigbluebutton.server_offline_threshold')) {
return ServerHealth::OFFLINE;
return ServerConnectionStatus::OFFLINE;
}

return ServerHealth::UNHEALTHY;
return ServerConnectionStatus::FAULTY;
Comment thread
samuelwei marked this conversation as resolved.
}
}
Comment thread
samuelwei marked this conversation as resolved.
2 changes: 1 addition & 1 deletion app/Models/ServerPool.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ServerPool extends Model
protected $fillable = ['name', 'description'];

/**
* Servers that are port of this server pool
* Servers that are part of this server pool
*/
public function servers(): BelongsToMany
{
Expand Down
28 changes: 14 additions & 14 deletions app/Observers/ServerObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace App\Observers;

use App\Enums\ServerHealth;
use App\Enums\ServerConnectionStatus;
use App\Enums\ServerStatus;
use App\Models\Server;
use Illuminate\Support\Facades\Log;
Expand Down Expand Up @@ -54,28 +54,28 @@ public function updated(Server $server): void
]);
}

// Check if server health changed
$newHealth = Server::calcHealth($server->recover_count, $server->error_count);
$previousHealth = Server::calcHealth($server->getOriginal('recover_count'), $server->getOriginal('error_count'));
if ($newHealth != $previousHealth) {
if ($newHealth == ServerHealth::OFFLINE) {
Log::error('Server {server} health changed to offline', [
// Check if server connection status changed
$newConnectionStatus = Server::calculateConnectionStatus($server->recover_count, $server->error_count);
$previousConnectionStatus = Server::calculateConnectionStatus($server->getOriginal('recover_count'), $server->getOriginal('error_count'));
if ($newConnectionStatus != $previousConnectionStatus) {
if ($newConnectionStatus == ServerConnectionStatus::OFFLINE) {
Log::error('Server {server} changed to offline', [
'server' => $server->getLogLabel(),
'old_health' => $previousHealth->name,
'old_connection_status' => $previousConnectionStatus->name,
]);
}

if ($newHealth == ServerHealth::UNHEALTHY) {
Log::warning('Server {server} health changed to unhealthy', [
if ($newConnectionStatus == ServerConnectionStatus::FAULTY) {
Log::warning('Server {server} changed to faulty', [
'server' => $server->getLogLabel(),
'old_health' => $previousHealth->name,
'old_connection_status' => $previousConnectionStatus->name,
]);
}

if ($newHealth == ServerHealth::ONLINE) {
Log::notice('Server {server} health changed to healthy', [
if ($newConnectionStatus == ServerConnectionStatus::ONLINE) {
Log::notice('Server {server} changed to online', [
'server' => $server->getLogLabel(),
'old_health' => $previousHealth->name,
'old_connection_status' => $previousConnectionStatus->name,
]);
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/Prometheus/Collectors/ServerCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public function collect(): void
->set(Server::where('status', ServerStatus::ENABLED)
->where('recover_count', '<', config('bigbluebutton.server_online_threshold'))
->where('error_count', '<', config('bigbluebutton.server_offline_threshold'))
->count(), ['unhealthy']);
->count(), ['faulty']);
}
}
19 changes: 11 additions & 8 deletions app/Services/LoadBalancingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
use App\Enums\ServerStatus;
use App\Models\Server;
use App\Models\ServerPool;
use Illuminate\Database\Eloquent\Builder;

class LoadBalancingService
{
private $servers;
private ServerPool $serverPool;

public function setServerPool(ServerPool $serverPool)
{
$this->servers = $serverPool->servers;
$this->serverPool = $serverPool;

return $this;
}
Expand All @@ -24,14 +25,16 @@ public function setServerPool(ServerPool $serverPool)
*/
public function getLowestUsageServer(): ?Server
{
return $this->servers
return $this->serverPool->servers()
->where('status', ServerStatus::ENABLED)
->where('recover_count', '>=', config('bigbluebutton.server_online_threshold'))
->where('error_count', '=', 0)
->whereNotNull('load')
->sortBy(function (Server $server) {
return $server->load / $server->strength;
->where(function (Builder $query) {
$query->where('recover_count', '>=', config('bigbluebutton.server_online_threshold'))
->where('error_count', '=', 0)
->orWhere('connection_status_always_online', true);
})
->whereNotNull('load')
->where('strength', '>', 0) // Extra safety against division by zero; request validation ensures strength is between 1 and 10
->orderByRaw('`load` / `strength`')
->first();
Comment thread
samuelwei marked this conversation as resolved.
}
}
30 changes: 18 additions & 12 deletions app/Services/ServerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace App\Services;

use App\Enums\ServerHealth;
use App\Enums\ServerConnectionStatus;
use App\Enums\ServerStatus;
use App\Models\Meeting;
use App\Models\MeetingStat;
Expand Down Expand Up @@ -87,7 +87,11 @@ private function getBBBVersion(): ?string
*/
public function handleApiCallFailed()
{
if ($this->server->health != ServerHealth::OFFLINE) {
if ($this->server->connection_status_always_online) {
return;
}

if ($this->server->connection_status != ServerConnectionStatus::OFFLINE) {
$this->server->error_count++;
}

Expand All @@ -96,23 +100,25 @@ public function handleApiCallFailed()
$this->server->timestamps = false;
$this->server->save();

if ($this->server->health == ServerHealth::OFFLINE) {
if ($this->server->connection_status == ServerConnectionStatus::OFFLINE) {
$this->setMeetingsDetached();
}
}

public function handleApiCallSuccessful()
{
if ($this->server->health != ServerHealth::ONLINE) {
$this->server->recover_count++;
}
if (! $this->server->connection_status_always_online) {
if ($this->server->connection_status != ServerConnectionStatus::ONLINE) {
$this->server->recover_count++;
}

if ($this->server->health == ServerHealth::ONLINE) {
$this->server->error_count = 0;
}
if ($this->server->connection_status == ServerConnectionStatus::ONLINE) {
$this->server->error_count = 0;
}

$this->server->timestamps = false;
$this->server->save();
$this->server->timestamps = false;
$this->server->save();
}

$this->endDetachedMeetings();

Expand Down Expand Up @@ -206,7 +212,7 @@ public function updateUsage($updateServerStatistics = false, $updateMeetingStati
$this->server->stats()->save($serverStat);
}

if ($this->server->health == ServerHealth::OFFLINE) {
if ($this->server->connection_status == ServerConnectionStatus::OFFLINE) {
// Clear current live server status
$this->server->participant_count = null;
$this->server->listener_count = null;
Expand Down
1 change: 1 addition & 0 deletions database/factories/ServerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function definition()
'version' => '2.4.5',
'strength' => 1,
'load' => 0,
'connection_status_always_online' => false,
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('servers', function (Blueprint $table) {
$table->boolean('connection_status_always_online')->default(false)->after('strength');
});
Comment thread
samuelwei marked this conversation as resolved.
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('servers', function (Blueprint $table) {
$table->dropColumn('connection_status_always_online');
});
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,21 @@ public function up(): void
$table->integer('recover_count')->default(0);
});

// Migrate the status column to health counters and status
// Migrate the status column to connection status counters and status
foreach (Server::all() as $server) {

switch ($server->getRawOriginal('status')) {
// Disabled
case -1:
case -1: // Disabled
$server->status = ServerStatus::DISABLED;
break;
// Offline
case 0:
// Server is unhealthy, but not offline yet
case 0: // Offline
// Server is faulty, but not offline yet
$server->recover_count = 0;
$server->error_count = 0;
$server->status = ServerStatus::ENABLED;
break;
// Online
case 1:
// Server is healthy
case 1: // Online
// Server is online
$server->recover_count = config('bigbluebutton.server_online_threshold');
$server->error_count = 0;
$server->status = ServerStatus::ENABLED;
Expand Down
Loading
Loading