Base implementation of smart deploy for servers, order screen, subscription service

This commit is contained in:
Marcel Baumgartner
2023-04-03 21:23:27 +02:00
parent a41a929e7f
commit 2298bab71e
9 changed files with 287 additions and 9 deletions

View 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; }
}

View File

@@ -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
{

View 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;
}
}

View File

@@ -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()
{