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

153 lines
6.3 KiB
C#
Raw Normal View History

2023-06-22 08:17:12 +00:00
using DistTestCore;
2023-06-22 12:37:37 +00:00
using DistTestCore.Codex;
using KubernetesWorkflow;
2023-06-26 13:37:16 +00:00
using Logging;
2023-06-22 08:17:12 +00:00
namespace CodexNetDeployer
{
public class Deployer
{
private readonly Configuration config;
2023-06-22 12:37:37 +00:00
private readonly DefaultTimeSet timeset;
private readonly PeerConnectivityChecker peerConnectivityChecker;
2023-06-22 08:17:12 +00:00
public Deployer(Configuration config)
{
this.config = config;
2023-06-22 12:37:37 +00:00
timeset = new DefaultTimeSet();
peerConnectivityChecker = new PeerConnectivityChecker();
2023-06-22 08:17:12 +00:00
}
public CodexDeployment Deploy()
2023-06-22 08:33:21 +00:00
{
Log("Initializing...");
var lifecycle = CreateTestLifecycle();
2023-06-22 08:33:21 +00:00
Log("Preparing configuration...");
2023-06-22 12:37:37 +00:00
// We trick the Geth companion node into unlocking all of its accounts, by saying we want to start 999 codex nodes.
var setup = new CodexSetup(999, config.CodexLogLevel);
setup.WithStorageQuota(config.StorageQuota!.Value.MB()).EnableMarketplace(0.TestTokens());
2023-08-13 07:07:23 +00:00
setup.MetricsMode = config.Metrics;
2023-06-22 08:33:21 +00:00
2023-06-22 12:37:37 +00:00
Log("Creating Geth instance and deploying contracts...");
var gethStarter = new GethStarter(lifecycle);
2023-06-22 12:37:37 +00:00
var gethResults = gethStarter.BringOnlineMarketplaceFor(setup);
2023-06-22 08:33:21 +00:00
2023-06-22 12:37:37 +00:00
Log("Geth started. Codex contracts deployed.");
Log("Warning: It can take up to 45 minutes for the Geth node to finish unlocking all if its 1000 preconfigured accounts.");
2023-06-22 12:37:37 +00:00
// It takes a second for the geth node to unlock a single account. Let's assume 3.
// We can't start the codex nodes until their accounts are definitely unlocked. So
// We wait:
Thread.Sleep(TimeSpan.FromSeconds(3.0 * config.NumberOfCodexNodes!.Value));
2023-06-22 12:37:37 +00:00
Log("Starting Codex nodes...");
// Each node must have its own IP, so it needs it own pod. Start them 1 at a time.
var codexStarter = new CodexNodeStarter(config, lifecycle, gethResults, 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
}
var (prometheusContainer, grafanaStartInfo) = StartMetricsService(lifecycle, setup, startResults.Select(r => r.Container));
2023-07-11 08:59:41 +00:00
CheckPeerConnectivity(startResults);
CheckContainerRestarts(startResults);
return new CodexDeployment(gethResults, startResults.Select(r => r.Container).ToArray(), prometheusContainer, grafanaStartInfo, CreateMetadata());
2023-06-22 08:33:21 +00:00
}
private TestLifecycle CreateTestLifecycle()
2023-06-22 08:17:12 +00:00
{
2023-06-27 06:29:39 +00:00
var kubeConfig = GetKubeConfig(config.KubeConfigFile);
2023-06-22 08:17:12 +00:00
var lifecycleConfig = new DistTestCore.Configuration
(
2023-06-27 06:29:39 +00:00
kubeConfigFile: kubeConfig,
2023-06-22 08:17:12 +00:00
logPath: "null",
logDebug: false,
dataFilesPath: "notUsed",
2023-06-22 08:33:21 +00:00
codexLogLevel: config.CodexLogLevel,
k8sNamespacePrefix: config.KubeNamespace
2023-06-22 08:17:12 +00:00
);
return new TestLifecycle(new NullLog(), lifecycleConfig, timeset, config.TestsTypePodLabel, string.Empty);
2023-06-22 08:33:21 +00:00
}
private (RunningContainer?, GrafanaStartInfo?) StartMetricsService(TestLifecycle lifecycle, CodexSetup setup, IEnumerable<RunningContainer> codexContainers)
2023-07-11 08:59:41 +00:00
{
2023-08-13 07:07:23 +00:00
if (setup.MetricsMode == DistTestCore.Metrics.MetricsMode.None) return (null, null);
2023-07-11 08:59:41 +00:00
Log("Starting metrics service...");
var runningContainers = new[] { new RunningContainers(null!, null!, codexContainers.ToArray()) };
2023-08-13 07:07:23 +00:00
var prometheusContainer = lifecycle.PrometheusStarter.CollectMetricsFor(runningContainers).Containers.Single();
if (setup.MetricsMode == DistTestCore.Metrics.MetricsMode.Record) return (prometheusContainer, null);
Log("Starting dashboard service...");
2023-08-14 08:26:04 +00:00
var grafanaStartInfo = lifecycle.GrafanaStarter.StartDashboard(prometheusContainer, setup);
2023-08-13 07:07:23 +00:00
return (prometheusContainer, grafanaStartInfo);
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;
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>();
foreach (var startResult in startResults)
{
var watcher = startResult.Workflow.CreateCrashWatcher(startResult.Container);
if (watcher.HasContainerCrashed()) crashes.Add(startResult.Container);
}
if (!crashes.Any())
{
Log("Container restart check passed.");
}
else
{
Log($"Deployment 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
}
}
}