Base implementation of smart deploy for servers, order screen, subscription service
This commit is contained in:
14
Moonlight/App/Models/Forms/ServerOrderDataModel.cs
Normal file
14
Moonlight/App/Models/Forms/ServerOrderDataModel.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.App.Database.Entities;
|
||||
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
public class ServerOrderDataModel
|
||||
{
|
||||
[Required(ErrorMessage = "You need to enter a name")]
|
||||
[MaxLength(32, ErrorMessage = "The name cannot be longer that 32 characters")]
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
[Required(ErrorMessage = "You need to specify a server image")]
|
||||
public Image Image { get; set; }
|
||||
}
|
||||
@@ -5,6 +5,12 @@ public class SubscriptionLimit
|
||||
public string Identifier { get; set; } = "";
|
||||
public int Amount { get; set; }
|
||||
public List<LimitOption> Options { get; set; } = new();
|
||||
|
||||
public string? ReadValue(string key)
|
||||
{
|
||||
var d = Options.FirstOrDefault(x => string.Equals(x.Key, key, StringComparison.InvariantCultureIgnoreCase));
|
||||
return d?.Value;
|
||||
}
|
||||
|
||||
public class LimitOption
|
||||
{
|
||||
|
||||
64
Moonlight/App/Services/SmartDeployService.cs
Normal file
64
Moonlight/App/Services/SmartDeployService.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Repositories;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
||||
public class SmartDeployService
|
||||
{
|
||||
private readonly NodeRepository NodeRepository;
|
||||
private readonly NodeService NodeService;
|
||||
|
||||
public SmartDeployService(NodeRepository nodeRepository, NodeService nodeService)
|
||||
{
|
||||
NodeRepository = nodeRepository;
|
||||
NodeService = nodeService;
|
||||
}
|
||||
|
||||
public async Task<Node?> GetNode()
|
||||
{
|
||||
var data = new Dictionary<Node, double>();
|
||||
|
||||
foreach (var node in NodeRepository.Get().ToArray())
|
||||
{
|
||||
var u = await GetUsageScore(node);
|
||||
|
||||
if(u != 0)
|
||||
data.Add(node, u);
|
||||
}
|
||||
|
||||
if (!data.Any())
|
||||
return null;
|
||||
|
||||
return data.MaxBy(x => x.Value).Key;
|
||||
}
|
||||
|
||||
private async Task<double> GetUsageScore(Node node)
|
||||
{
|
||||
var score = 0;
|
||||
|
||||
try
|
||||
{
|
||||
var cpuStats = await NodeService.GetCpuStats(node);
|
||||
var memoryStats = await NodeService.GetMemoryStats(node);
|
||||
var diskStats = await NodeService.GetDiskStats(node);
|
||||
|
||||
var cpuWeight = 0.5; // Weight of CPU usage in the final score
|
||||
var memoryWeight = 0.3; // Weight of memory usage in the final score
|
||||
var diskSpaceWeight = 0.2; // Weight of free disk space in the final score
|
||||
|
||||
var cpuScore = (1 - cpuStats.Usage) * cpuWeight; // CPU score is based on the inverse of CPU usage
|
||||
var memoryScore = (1 - (memoryStats.Used / 1024)) * memoryWeight; // Memory score is based on the percentage of free memory
|
||||
var diskSpaceScore = (double) diskStats.FreeBytes / 1000000000 * diskSpaceWeight; // Disk space score is based on the amount of free disk space in GB
|
||||
|
||||
var finalScore = cpuScore + memoryScore + diskSpaceScore;
|
||||
|
||||
return finalScore;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
}
|
||||
@@ -82,16 +82,19 @@ public class SubscriptionService
|
||||
{
|
||||
var configSection = ConfigService.GetSection("Moonlight").GetSection("Subscriptions");
|
||||
|
||||
var defaultLimits = configSection.GetValue<SubscriptionLimit[]>("defaultLimits");
|
||||
var defaultLimits = configSection.GetValue<SubscriptionLimit[]>("DefaultLimits");
|
||||
|
||||
var subscription = await GetCurrent();
|
||||
|
||||
if (subscription == null)
|
||||
{
|
||||
var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier);
|
||||
if (defaultLimits != null)
|
||||
{
|
||||
var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier);
|
||||
|
||||
if (foundDefault != null)
|
||||
return foundDefault;
|
||||
if (foundDefault != null)
|
||||
return foundDefault;
|
||||
}
|
||||
|
||||
return new()
|
||||
{
|
||||
@@ -109,11 +112,14 @@ public class SubscriptionService
|
||||
|
||||
if (foundLimit != null)
|
||||
return foundLimit;
|
||||
|
||||
var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier);
|
||||
|
||||
if (foundDefault != null)
|
||||
return foundDefault;
|
||||
if (defaultLimits != null)
|
||||
{
|
||||
var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier);
|
||||
|
||||
if (foundDefault != null)
|
||||
return foundDefault;
|
||||
}
|
||||
|
||||
return new()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user