Add CPU limit to node (#239) to resolve #233

* add node cpu limit to backend

* update makenodecommand

* add node cpu limit to frontend

* add migration and update mysql schema

* run pint

* fix typo in mysql schema

* forgot this assert

* forgot to setCpu here

* run pint

* adjust migration

* Fix db migration

* make cpu optional

* set default value for cpu in node deployment

* update mysql schema

---------

Co-authored-by: notCharles <charles@pelican.dev>
This commit is contained in:
Boy132 2024-05-22 08:34:43 +02:00 committed by GitHub
parent eadaec1b30
commit 4dd833562b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 195 additions and 28 deletions

View File

@ -20,6 +20,8 @@ class MakeNodeCommand extends Command
{--overallocateMemory= : Enter the amount of ram to overallocate (% or -1 to overallocate the maximum).} {--overallocateMemory= : Enter the amount of ram to overallocate (% or -1 to overallocate the maximum).}
{--maxDisk= : Set the max disk amount.} {--maxDisk= : Set the max disk amount.}
{--overallocateDisk= : Enter the amount of disk to overallocate (% or -1 to overallocate the maximum).} {--overallocateDisk= : Enter the amount of disk to overallocate (% or -1 to overallocate the maximum).}
{--maxCpu= : Set the max cpu amount.}
{--overallocateCpu= : Enter the amount of cpu to overallocate (% or -1 to overallocate the maximum).}
{--uploadSize= : Enter the maximum upload filesize.} {--uploadSize= : Enter the maximum upload filesize.}
{--daemonListeningPort= : Enter the daemon listening port.} {--daemonListeningPort= : Enter the daemon listening port.}
{--daemonSFTPPort= : Enter the daemon SFTP listening port.} {--daemonSFTPPort= : Enter the daemon SFTP listening port.}
@ -58,6 +60,8 @@ class MakeNodeCommand extends Command
$data['memory_overallocate'] = $this->option('overallocateMemory') ?? $this->ask(__('commands.make_node.memory_overallocate')); $data['memory_overallocate'] = $this->option('overallocateMemory') ?? $this->ask(__('commands.make_node.memory_overallocate'));
$data['disk'] = $this->option('maxDisk') ?? $this->ask(__('commands.make_node.disk')); $data['disk'] = $this->option('maxDisk') ?? $this->ask(__('commands.make_node.disk'));
$data['disk_overallocate'] = $this->option('overallocateDisk') ?? $this->ask(__('commands.make_node.disk_overallocate')); $data['disk_overallocate'] = $this->option('overallocateDisk') ?? $this->ask(__('commands.make_node.disk_overallocate'));
$data['cpu'] = $this->option('maxCpu') ?? $this->ask(__('commands.make_node.cpu'));
$data['cpu_overallocate'] = $this->option('overallocateCpu') ?? $this->ask(__('commands.make_node.cpu_overallocate'));
$data['upload_size'] = $this->option('uploadSize') ?? $this->ask(__('commands.make_node.upload_size'), '100'); $data['upload_size'] = $this->option('uploadSize') ?? $this->ask(__('commands.make_node.upload_size'), '100');
$data['daemon_listen'] = $this->option('daemonListeningPort') ?? $this->ask(__('commands.make_node.daemonListen'), '8080'); $data['daemon_listen'] = $this->option('daemonListeningPort') ?? $this->ask(__('commands.make_node.daemonListen'), '8080');
$data['daemon_sftp'] = $this->option('daemonSFTPPort') ?? $this->ask(__('commands.make_node.daemonSFTP'), '2022'); $data['daemon_sftp'] = $this->option('daemonSFTPPort') ?? $this->ask(__('commands.make_node.daemonSFTP'), '2022');

View File

@ -311,6 +311,45 @@ class CreateNode extends CreateRecord
->default(0) ->default(0)
->suffix('%'), ->suffix('%'),
]), ]),
Forms\Components\Grid::make()
->columns(6)
->columnSpanFull()
->schema([
Forms\Components\ToggleButtons::make('unlimited_cpu')
->label('CPU')->inlineLabel()->inline()
->live()
->afterStateUpdated(fn (Forms\Set $set) => $set('cpu', 0))
->afterStateUpdated(fn (Forms\Set $set) => $set('cpu_overallocate', 0))
->formatStateUsing(fn (Forms\Get $get) => $get('cpu') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
])
->colors([
true => 'primary',
false => 'warning',
])
->columnSpan(2),
Forms\Components\TextInput::make('cpu')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_cpu'))
->label('CPU Limit')->inlineLabel()
->suffix('%')
->columnSpan(2)
->numeric()
->minValue(0),
Forms\Components\TextInput::make('cpu_overallocate')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_cpu'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
->columnSpan(2)
->numeric()
->minValue(-1)
->maxValue(100)
->suffix('%'),
]),
]), ]),
]), ]),
]); ]);

View File

@ -318,6 +318,47 @@ class EditNode extends EditRecord
->maxValue(100) ->maxValue(100)
->suffix('%'), ->suffix('%'),
]), ]),
Forms\Components\Grid::make()
->columns(6)
->columnSpanFull()
->schema([
Forms\Components\ToggleButtons::make('unlimited_cpu')
->label('CPU')->inlineLabel()->inline()
->live()
->afterStateUpdated(fn (Forms\Set $set) => $set('cpu', 0))
->afterStateUpdated(fn (Forms\Set $set) => $set('cpu_overallocate', 0))
->formatStateUsing(fn (Forms\Get $get) => $get('cpu') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
])
->colors([
true => 'primary',
false => 'warning',
])
->columnSpan(2),
Forms\Components\TextInput::make('cpu')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_cpu'))
->label('CPU Limit')->inlineLabel()
->suffix('%')
->required()
->columnSpan(2)
->numeric()
->minValue(0),
Forms\Components\TextInput::make('cpu_overallocate')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_cpu'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
->columnSpan(2)
->required()
->numeric()
->minValue(-1)
->maxValue(100)
->suffix('%'),
]),
]), ]),
Tabs\Tab::make('Configuration File') Tabs\Tab::make('Configuration File')
->icon('tabler-code') ->icon('tabler-code')

View File

@ -52,6 +52,12 @@ class ListNodes extends ListRecords
->suffix(' GiB') ->suffix(' GiB')
->formatStateUsing(fn ($state) => number_format($state / 1024, 2)) ->formatStateUsing(fn ($state) => number_format($state / 1024, 2))
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('cpu')
->visibleFrom('sm')
->icon('tabler-file')
->numeric()
->suffix(' %')
->sortable(),
Tables\Columns\IconColumn::make('scheme') Tables\Columns\IconColumn::make('scheme')
->visibleFrom('xl') ->visibleFrom('xl')
->label('SSL') ->label('SSL')

View File

@ -36,7 +36,7 @@ class NodeController extends ApplicationApiController
{ {
$nodes = QueryBuilder::for(Node::query()) $nodes = QueryBuilder::for(Node::query())
->allowedFilters(['uuid', 'name', 'fqdn', 'daemon_token_id']) ->allowedFilters(['uuid', 'name', 'fqdn', 'daemon_token_id'])
->allowedSorts(['id', 'uuid', 'memory', 'disk']) ->allowedSorts(['id', 'uuid', 'memory', 'disk', 'cpu'])
->paginate($request->query('per_page') ?? 50); ->paginate($request->query('per_page') ?? 50);
return $this->fractal->collection($nodes) return $this->fractal->collection($nodes)

View File

@ -30,6 +30,7 @@ class NodeDeploymentController extends ApplicationApiController
$nodes = $this->viableNodesService $nodes = $this->viableNodesService
->setMemory($data['memory']) ->setMemory($data['memory'])
->setDisk($data['disk']) ->setDisk($data['disk'])
->setCpu($data['cpu'] ?? 0)
->handle((int) $request->query('per_page'), (int) $request->query('page')); ->handle((int) $request->query('per_page'), (int) $request->query('page'));
return $this->fractal->collection($nodes) return $this->fractal->collection($nodes)

View File

@ -10,6 +10,7 @@ class GetDeployableNodesRequest extends GetNodesRequest
'page' => 'integer', 'page' => 'integer',
'memory' => 'required|integer|min:0', 'memory' => 'required|integer|min:0',
'disk' => 'required|integer|min:0', 'disk' => 'required|integer|min:0',
'cpu' => 'sometimes|integer|min:0',
]; ];
} }
} }

View File

@ -28,6 +28,8 @@ class StoreNodeRequest extends ApplicationApiRequest
'memory_overallocate', 'memory_overallocate',
'disk', 'disk',
'disk_overallocate', 'disk_overallocate',
'cpu',
'cpu_overallocate',
'upload_size', 'upload_size',
'daemon_listen', 'daemon_listen',
'daemon_sftp', 'daemon_sftp',

View File

@ -26,6 +26,8 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough;
* @property int $memory_overallocate * @property int $memory_overallocate
* @property int $disk * @property int $disk
* @property int $disk_overallocate * @property int $disk_overallocate
* @property int $cpu
* @property int $cpu_overallocate
* @property int $upload_size * @property int $upload_size
* @property string $daemon_token_id * @property string $daemon_token_id
* @property string $daemon_token * @property string $daemon_token
@ -63,6 +65,7 @@ class Node extends Model
public int $sum_memory; public int $sum_memory;
public int $sum_disk; public int $sum_disk;
public int $sum_cpu;
/** /**
* Fields that are mass assignable. * Fields that are mass assignable.
@ -71,7 +74,8 @@ class Node extends Model
'public', 'name', 'public', 'name',
'fqdn', 'scheme', 'behind_proxy', 'fqdn', 'scheme', 'behind_proxy',
'memory', 'memory_overallocate', 'disk', 'memory', 'memory_overallocate', 'disk',
'disk_overallocate', 'upload_size', 'daemon_base', 'disk_overallocate', 'cpu', 'cpu_overallocate',
'upload_size', 'daemon_base',
'daemon_sftp', 'daemon_listen', 'daemon_sftp', 'daemon_listen',
'description', 'maintenance_mode', 'description', 'maintenance_mode',
]; ];
@ -87,6 +91,8 @@ class Node extends Model
'memory_overallocate' => 'required|numeric|min:-1', 'memory_overallocate' => 'required|numeric|min:-1',
'disk' => 'required|numeric|min:0', 'disk' => 'required|numeric|min:0',
'disk_overallocate' => 'required|numeric|min:-1', 'disk_overallocate' => 'required|numeric|min:-1',
'cpu' => 'required|numeric|min:0',
'cpu_overallocate' => 'required|numeric|min:-1',
'daemon_base' => 'sometimes|required|regex:/^([\/][\d\w.\-\/]+)$/', 'daemon_base' => 'sometimes|required|regex:/^([\/][\d\w.\-\/]+)$/',
'daemon_sftp' => 'required|numeric|between:1,65535', 'daemon_sftp' => 'required|numeric|between:1,65535',
'daemon_listen' => 'required|numeric|between:1,65535', 'daemon_listen' => 'required|numeric|between:1,65535',
@ -104,6 +110,8 @@ class Node extends Model
'memory_overallocate' => 0, 'memory_overallocate' => 0,
'disk' => 0, 'disk' => 0,
'disk_overallocate' => 0, 'disk_overallocate' => 0,
'cpu' => 0,
'cpu_overallocate' => 0,
'daemon_base' => '/var/lib/pelican/volumes', 'daemon_base' => '/var/lib/pelican/volumes',
'daemon_sftp' => 2022, 'daemon_sftp' => 2022,
'daemon_listen' => 8080, 'daemon_listen' => 8080,
@ -116,6 +124,7 @@ class Node extends Model
return [ return [
'memory' => 'integer', 'memory' => 'integer',
'disk' => 'integer', 'disk' => 'integer',
'cpu' => 'integer',
'daemon_listen' => 'integer', 'daemon_listen' => 'integer',
'daemon_sftp' => 'integer', 'daemon_sftp' => 'integer',
'behind_proxy' => 'boolean', 'behind_proxy' => 'boolean',
@ -239,12 +248,13 @@ class Node extends Model
/** /**
* Returns a boolean if the node is viable for an additional server to be placed on it. * Returns a boolean if the node is viable for an additional server to be placed on it.
*/ */
public function isViable(int $memory, int $disk): bool public function isViable(int $memory, int $disk, int $cpu): bool
{ {
$memoryLimit = $this->memory * (1 + ($this->memory_overallocate / 100)); $memoryLimit = $this->memory * (1 + ($this->memory_overallocate / 100));
$diskLimit = $this->disk * (1 + ($this->disk_overallocate / 100)); $diskLimit = $this->disk * (1 + ($this->disk_overallocate / 100));
$cpuLimit = $this->cpu * (1 + ($this->cpu_overallocate / 100));
return ($this->sum_memory + $memory) <= $memoryLimit && ($this->sum_disk + $disk) <= $diskLimit; return ($this->sum_memory + $memory) <= $memoryLimit && ($this->sum_disk + $disk) <= $diskLimit && ($this->sum_cpu + $cpu) <= $cpuLimit;
} }
public static function getForServerCreation() public static function getForServerCreation()

View File

@ -10,8 +10,20 @@ use App\Exceptions\Service\Deployment\NoViableNodeException;
class FindViableNodesService class FindViableNodesService
{ {
protected ?int $disk = null;
protected ?int $memory = null; protected ?int $memory = null;
protected ?int $disk = null;
protected ?int $cpu = null;
/**
* Set the amount of memory that this server will be using. As with disk space, nodes that
* do not have enough free memory will be filtered out.
*/
public function setMemory(int $memory): self
{
$this->memory = $memory;
return $this;
}
/** /**
* Set the amount of disk that will be used by the server being created. Nodes will be * Set the amount of disk that will be used by the server being created. Nodes will be
@ -26,12 +38,13 @@ class FindViableNodesService
} }
/** /**
* Set the amount of memory that this server will be using. As with disk space, nodes that * Set the amount of cpu that will be used by the server being created. Nodes will be
* do not have enough free memory will be filtered out. * filtered out if they do not have enough available free cpu for this server
* to be placed on.
*/ */
public function setMemory(int $memory): self public function setCpu(int $cpu): self
{ {
$this->memory = $memory; $this->cpu = $cpu;
return $this; return $this;
} }
@ -41,8 +54,8 @@ class FindViableNodesService
* be passed to the AllocationSelectionService to return a single allocation. * be passed to the AllocationSelectionService to return a single allocation.
* *
* This functionality is used for automatic deployments of servers and will * This functionality is used for automatic deployments of servers and will
* attempt to find all nodes in the defined locations that meet the disk and * attempt to find all nodes in the defined locations that meet the memory, disk
* memory availability requirements. Any nodes not meeting those requirements * and cpu availability requirements. Any nodes not meeting those requirements
* are tossed out, as are any nodes marked as non-public, meaning automatic * are tossed out, as are any nodes marked as non-public, meaning automatic
* deployments should not be done against them. * deployments should not be done against them.
* *
@ -55,18 +68,21 @@ class FindViableNodesService
*/ */
public function handle(int $perPage = null, int $page = null): LengthAwarePaginator|Collection public function handle(int $perPage = null, int $page = null): LengthAwarePaginator|Collection
{ {
Assert::integer($this->disk, 'Disk space must be an int, got %s');
Assert::integer($this->memory, 'Memory usage must be an int, got %s'); Assert::integer($this->memory, 'Memory usage must be an int, got %s');
Assert::integer($this->disk, 'Disk space must be an int, got %s');
Assert::integer($this->cpu, 'CPU must be an int, got %s');
$query = Node::query()->select('nodes.*') $query = Node::query()->select('nodes.*')
->selectRaw('IFNULL(SUM(servers.memory), 0) as sum_memory') ->selectRaw('IFNULL(SUM(servers.memory), 0) as sum_memory')
->selectRaw('IFNULL(SUM(servers.disk), 0) as sum_disk') ->selectRaw('IFNULL(SUM(servers.disk), 0) as sum_disk')
->selectRaw('IFNULL(SUM(servers.cpu), 0) as sum_cpu')
->leftJoin('servers', 'servers.node_id', '=', 'nodes.id') ->leftJoin('servers', 'servers.node_id', '=', 'nodes.id')
->where('nodes.public', 1); ->where('nodes.public', 1);
$results = $query->groupBy('nodes.id') $results = $query->groupBy('nodes.id')
->havingRaw('(IFNULL(SUM(servers.memory), 0) + ?) <= (nodes.memory * (1 + (nodes.memory_overallocate / 100)))', [$this->memory]) ->havingRaw('(IFNULL(SUM(servers.memory), 0) + ?) <= (nodes.memory * (1 + (nodes.memory_overallocate / 100)))', [$this->memory])
->havingRaw('(IFNULL(SUM(servers.disk), 0) + ?) <= (nodes.disk * (1 + (nodes.disk_overallocate / 100)))', [$this->disk]); ->havingRaw('(IFNULL(SUM(servers.disk), 0) + ?) <= (nodes.disk * (1 + (nodes.disk_overallocate / 100)))', [$this->disk])
->havingRaw('(IFNULL(SUM(servers.cpu), 0) + ?) <= (nodes.cpu * (1 + (nodes.cpu_overallocate / 100)))', [$this->cpu]);
if (!is_null($page)) { if (!is_null($page)) {
$results = $results->paginate($perPage ?? 50, ['*'], 'page', $page); $results = $results->paginate($perPage ?? 50, ['*'], 'page', $page);

View File

@ -111,8 +111,9 @@ class ServerCreationService
{ {
/** @var \Illuminate\Support\Collection $nodes */ /** @var \Illuminate\Support\Collection $nodes */
$nodes = $this->findViableNodesService $nodes = $this->findViableNodesService
->setDisk(Arr::get($data, 'disk'))
->setMemory(Arr::get($data, 'memory')) ->setMemory(Arr::get($data, 'memory'))
->setDisk(Arr::get($data, 'disk'))
->setCpu(Arr::get($data, 'cpu'))
->handle(); ->handle();
return $this->allocationSelectionService->setDedicated($deployment->isDedicated()) return $this->allocationSelectionService->setDedicated($deployment->isDedicated())

View File

@ -57,13 +57,13 @@ class TransferServerService
// Check if the node is viable for the transfer. // Check if the node is viable for the transfer.
$node = Node::query() $node = Node::query()
->select(['nodes.id', 'nodes.fqdn', 'nodes.scheme', 'nodes.daemon_token', 'nodes.daemon_listen', 'nodes.memory', 'nodes.disk', 'nodes.memory_overallocate', 'nodes.disk_overallocate']) ->select(['nodes.id', 'nodes.fqdn', 'nodes.scheme', 'nodes.daemon_token', 'nodes.daemon_listen', 'nodes.memory', 'nodes.disk', 'nodes.cpu', 'nodes.memory_overallocate', 'nodes.disk_overallocate', 'nodes.cpu_overallocate'])
->selectRaw('IFNULL(SUM(servers.memory), 0) as sum_memory, IFNULL(SUM(servers.disk), 0) as sum_disk') ->selectRaw('IFNULL(SUM(servers.memory), 0) as sum_memory, IFNULL(SUM(servers.disk), 0) as sum_disk, IFNULL(SUM(servers.cpu), 0) as sum_cpu')
->leftJoin('servers', 'servers.node_id', '=', 'nodes.id') ->leftJoin('servers', 'servers.node_id', '=', 'nodes.id')
->where('nodes.id', $node_id) ->where('nodes.id', $node_id)
->first(); ->first();
if (!$node->isViable($server->memory, $server->disk)) { if (!$node->isViable($server->memory, $server->disk, $server->cpu)) {
return false; return false;
} }

View File

@ -34,11 +34,12 @@ class NodeTransformer extends BaseTransformer
$response[$node->getUpdatedAtColumn()] = $this->formatTimestamp($node->updated_at); $response[$node->getUpdatedAtColumn()] = $this->formatTimestamp($node->updated_at);
$response[$node->getCreatedAtColumn()] = $this->formatTimestamp($node->created_at); $response[$node->getCreatedAtColumn()] = $this->formatTimestamp($node->created_at);
$resources = $node->servers()->select(['memory', 'disk'])->get(); $resources = $node->servers()->select(['memory', 'disk', 'cpu'])->get();
$response['allocated_resources'] = [ $response['allocated_resources'] = [
'memory' => $resources->sum('memory'), 'memory' => $resources->sum('memory'),
'disk' => $resources->sum('disk'), 'disk' => $resources->sum('disk'),
'cpu' => $resources->sum('cpu'),
]; ];
return $response; return $response;

View File

@ -33,6 +33,8 @@ class NodeFactory extends Factory
'memory_overallocate' => 0, 'memory_overallocate' => 0,
'disk' => 10240, 'disk' => 10240,
'disk_overallocate' => 0, 'disk_overallocate' => 0,
'cpu' => 100,
'cpu_overallocate' => 0,
'upload_size' => 100, 'upload_size' => 100,
'daemon_token_id' => Str::random(Node::DAEMON_TOKEN_ID_LENGTH), 'daemon_token_id' => Str::random(Node::DAEMON_TOKEN_ID_LENGTH),
'daemon_token' => Crypt::encrypt(Str::random(Node::DAEMON_TOKEN_LENGTH)), 'daemon_token' => Crypt::encrypt(Str::random(Node::DAEMON_TOKEN_LENGTH)),

View File

@ -0,0 +1,30 @@
<?php
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('nodes', function (Blueprint $table) {
$table->unsignedInteger('cpu')->default(0)->after('disk_overallocate');
$table->integer('cpu_overallocate')->default(0)->after('cpu');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('nodes', function (Blueprint $table) {
$table->dropColumn('cpu');
$table->dropColumn('cpu_overallocate');
});
}
};

View File

@ -359,6 +359,8 @@ CREATE TABLE `nodes` (
`memory_overallocate` int NOT NULL DEFAULT '0', `memory_overallocate` int NOT NULL DEFAULT '0',
`disk` int unsigned NOT NULL, `disk` int unsigned NOT NULL,
`disk_overallocate` int NOT NULL DEFAULT '0', `disk_overallocate` int NOT NULL DEFAULT '0',
`cpu` int unsigned NOT NULL DEFAULT '0',
`cpu_overallocate` int NOT NULL DEFAULT '0',
`upload_size` int unsigned NOT NULL DEFAULT '100', `upload_size` int unsigned NOT NULL DEFAULT '100',
`daemon_token_id` char(16) COLLATE utf8mb4_unicode_ci NOT NULL, `daemon_token_id` char(16) COLLATE utf8mb4_unicode_ci NOT NULL,
`daemon_token` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, `daemon_token` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
@ -845,3 +847,4 @@ INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (198,'2024_03_14_05
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (201,'2024_04_20_214441_add_egg_var_sort',3); INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (201,'2024_04_20_214441_add_egg_var_sort',3);
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (203,'2024_04_14_002250_update_column_names',4); INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (203,'2024_04_14_002250_update_column_names',4);
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (204,'2024_05_08_094823_rename_oom_disabled_column_to_oom_killer',1); INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (204,'2024_05_08_094823_rename_oom_disabled_column_to_oom_killer',1);
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (205,'2024_05_16_091207_add_cpu_columns_to_nodes_table',1);

View File

@ -31,7 +31,9 @@ return [
'memory' => 'Enter the maximum amount of memory', 'memory' => 'Enter the maximum amount of memory',
'memory_overallocate' => 'Enter the amount of memory to over allocate by, -1 will disable checking and 0 will prevent creating new servers', 'memory_overallocate' => 'Enter the amount of memory to over allocate by, -1 will disable checking and 0 will prevent creating new servers',
'disk' => 'Enter the maximum amount of disk space', 'disk' => 'Enter the maximum amount of disk space',
'disk_overallocate' => 'Enter the amount of memory to over allocate by, -1 will disable checking and 0 will prevent creating new server', 'disk_overallocate' => 'Enter the amount of disk to over allocate by, -1 will disable checking and 0 will prevent creating new server',
'cpu' => 'Enter the maximum amount of cpu',
'cpu_overallocate' => 'Enter the amount of cpu to over allocate by, -1 will disable checking and 0 will prevent creating new server',
'upload_size' => "'Enter the maximum filesize upload", 'upload_size' => "'Enter the maximum filesize upload",
'daemonListen' => 'Enter the daemon listening port', 'daemonListen' => 'Enter the daemon listening port',
'daemonSFTP' => 'Enter the daemon SFTP listening port', 'daemonSFTP' => 'Enter the daemon SFTP listening port',

View File

@ -19,20 +19,28 @@ class FindViableNodesServiceTest extends IntegrationTestCase
Node::query()->delete(); Node::query()->delete();
} }
public function testExceptionIsThrownIfNoDiskSpaceHasBeenSet(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Disk space must be an int, got NULL');
$this->getService()->handle();
}
public function testExceptionIsThrownIfNoMemoryHasBeenSet(): void public function testExceptionIsThrownIfNoMemoryHasBeenSet(): void
{ {
$this->expectException(\InvalidArgumentException::class); $this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Memory usage must be an int, got NULL'); $this->expectExceptionMessage('Memory usage must be an int, got NULL');
$this->getService()->setDisk(10)->handle(); $this->getService()->setDisk(10)->setCpu(10)->handle();
}
public function testExceptionIsThrownIfNoDiskSpaceHasBeenSet(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Disk space must be an int, got NULL');
$this->getService()->setMemory(10)->setCpu(10)->handle();
}
public function testExceptionIsThrownIfNoCpuHasBeenSet(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('CPU must be an int, got NULL');
$this->getService()->setMemory(10)->setDisk(10)->handle();
} }
private function getService(): FindViableNodesService private function getService(): FindViableNodesService