cs-codex-dist-tests/Tools/CodexNetDeployer/Deployer.cs

161 lines
5.8 KiB
C#
Raw Normal View History

2023-09-20 10:02:32 +00:00
using CodexContractsPlugin;
using CodexPlugin;
using Core;
using GethPlugin;
2023-06-22 12:37:37 +00:00
using KubernetesWorkflow;
2023-06-26 13:37:16 +00:00
using Logging;
2023-09-20 10:02:32 +00:00
using MetricsPlugin;
2023-06-22 08:17:12 +00:00
namespace CodexNetDeployer
{
public class Deployer
{
private readonly Configuration config;
private readonly PeerConnectivityChecker peerConnectivityChecker;
2023-09-20 10:02:32 +00:00
private readonly EntryPoint entryPoint;
2023-06-22 08:17:12 +00:00
public Deployer(Configuration config)
{
this.config = config;
peerConnectivityChecker = new PeerConnectivityChecker();
2023-09-20 11:56:01 +00:00
ProjectPlugin.Load<CodexPlugin.CodexPlugin>();
ProjectPlugin.Load<CodexContractsPlugin.CodexContractsPlugin>();
ProjectPlugin.Load<GethPlugin.GethPlugin>();
ProjectPlugin.Load<MetricsPlugin.MetricsPlugin>();
2023-09-20 10:02:32 +00:00
entryPoint = CreateEntryPoint(new NullLog());
2023-06-22 08:17:12 +00:00
}
2023-09-20 10:02:32 +00:00
public void AnnouncePlugins()
2023-06-22 08:33:21 +00:00
{
2023-09-20 10:02:32 +00:00
var ep = CreateEntryPoint(new ConsoleLog());
2023-06-22 08:33:21 +00:00
2023-09-20 10:02:32 +00:00
Log("Using plugins:" + Environment.NewLine);
var metadata = ep.GetPluginMetadata();
foreach (var entry in metadata)
{
Log($"{entry.Key} = {entry.Value}");
}
Log("");
}
2023-06-22 08:33:21 +00:00
2023-09-20 10:02:32 +00:00
public CodexDeployment Deploy()
{
Log("Initializing...");
var ci = entryPoint.CreateInterface();
2023-06-22 08:33:21 +00:00
2023-09-20 10:02:32 +00:00
Log("Deploying Geth instance...");
var gethDeployment = ci.DeployGeth(s => s.IsMiner());
var gethNode = ci.WrapGethDeployment(gethDeployment);
2023-06-22 12:37:37 +00:00
2023-09-20 10:02:32 +00:00
Log("Geth started. Deploying Codex contracts...");
var contractsDeployment = ci.DeployCodexContracts(gethNode);
var contracts = ci.WrapCodexContractsDeployment(contractsDeployment);
Log("Codex contracts deployed.");
2023-06-22 12:37:37 +00:00
Log("Starting Codex nodes...");
2023-09-20 10:02:32 +00:00
var codexStarter = new CodexNodeStarter(config, ci, gethNode, contracts, config.NumberOfValidators!.Value);
var startResults = new List<CodexNodeStartResult>();
2023-06-22 12:37:37 +00:00
for (var i = 0; i < config.NumberOfCodexNodes; i++)
2023-06-22 08:33:21 +00:00
{
var result = codexStarter.Start(i);
if (result != null) startResults.Add(result);
2023-06-22 08:33:21 +00:00
}
2023-09-20 10:02:32 +00:00
Log("Codex nodes started.");
var metricsService = StartMetricsService(ci, startResults);
2023-07-11 08:59:41 +00:00
CheckPeerConnectivity(startResults);
CheckContainerRestarts(startResults);
2023-09-20 10:02:32 +00:00
var codexContainers = startResults.Select(s => s.CodexNode.Container).ToArray();
return new CodexDeployment(codexContainers, gethDeployment, metricsService, CreateMetadata());
2023-06-22 08:33:21 +00:00
}
2023-09-20 10:02:32 +00:00
private EntryPoint CreateEntryPoint(ILog log)
2023-06-22 08:17:12 +00:00
{
2023-06-27 06:29:39 +00:00
var kubeConfig = GetKubeConfig(config.KubeConfigFile);
2023-09-20 10:02:32 +00:00
var configuration = new KubernetesWorkflow.Configuration(
kubeConfig,
operationTimeout: TimeSpan.FromSeconds(30),
retryDelay: TimeSpan.FromSeconds(10),
kubernetesNamespace: config.KubeNamespace);
return new EntryPoint(log, configuration, string.Empty);
2023-06-22 08:33:21 +00:00
}
2023-09-20 10:02:32 +00:00
private RunningContainer? StartMetricsService(CoreInterface ci, List<CodexNodeStartResult> startResults)
2023-07-11 08:59:41 +00:00
{
2023-09-20 10:02:32 +00:00
if (!config.Metrics) return null;
2023-07-11 08:59:41 +00:00
Log("Starting metrics service...");
2023-08-13 07:07:23 +00:00
2023-09-20 10:02:32 +00:00
var runningContainer = ci.DeployMetricsCollector(startResults.Select(r => r.CodexNode).ToArray());
Log("Metrics service started.");
2023-08-13 07:07:23 +00:00
2023-09-20 10:02:32 +00:00
return runningContainer;
2023-07-11 08:59:41 +00:00
}
2023-06-27 06:29:39 +00:00
private string? GetKubeConfig(string kubeConfigFile)
{
if (string.IsNullOrEmpty(kubeConfigFile) || kubeConfigFile.ToLowerInvariant() == "null") return null;
return kubeConfigFile;
}
private void CheckPeerConnectivity(List<CodexNodeStartResult> codexContainers)
{
if (!config.CheckPeerConnection) return;
2023-09-20 10:02:32 +00:00
Log("Starting peer connectivity check for deployed nodes...");
peerConnectivityChecker.CheckConnectivity(codexContainers);
Log("Check passed.");
}
private void CheckContainerRestarts(List<CodexNodeStartResult> startResults)
{
var crashes = new List<RunningContainer>();
2023-09-20 10:02:32 +00:00
Log("Starting container crash check...");
foreach (var startResult in startResults)
{
2023-09-20 10:55:09 +00:00
var watcher = startResult.CodexNode.CrashWatcher;
2023-09-20 10:02:32 +00:00
if (watcher == null) throw new Exception("Expected each CodexNode container to be created with a crash-watcher.");
if (watcher.HasContainerCrashed()) crashes.Add(startResult.CodexNode.Container);
}
if (!crashes.Any())
{
2023-09-20 10:02:32 +00:00
Log("Check passed.");
}
else
{
2023-09-20 10:02:32 +00:00
Log($"Check failed. The following containers have crashed: {string.Join(",", crashes.Select(c => c.Name))}");
throw new Exception("Deployment failed: One or more containers crashed.");
}
}
2023-06-23 07:08:18 +00:00
private DeploymentMetadata CreateMetadata()
{
return new DeploymentMetadata(
kubeNamespace: config.KubeNamespace,
numberOfCodexNodes: config.NumberOfCodexNodes!.Value,
numberOfValidators: config.NumberOfValidators!.Value,
storageQuotaMB: config.StorageQuota!.Value,
codexLogLevel: config.CodexLogLevel,
initialTestTokens: config.InitialTestTokens,
minPrice: config.MinPrice,
maxCollateral: config.MaxCollateral,
maxDuration: config.MaxDuration,
blockTTL: config.BlockTTL,
blockMI: config.BlockMI,
blockMN: config.BlockMN);
2023-06-23 07:08:18 +00:00
}
2023-06-22 08:33:21 +00:00
private void Log(string msg)
{
Console.WriteLine(msg);
2023-06-22 08:17:12 +00:00
}
}
}