2023-11-06 14:33:47 +01:00
|
|
|
|
using GethPlugin;
|
|
|
|
|
using KubernetesWorkflow;
|
2023-11-12 10:07:23 +01:00
|
|
|
|
using KubernetesWorkflow.Recipe;
|
2023-09-08 09:39:56 +02:00
|
|
|
|
using Utils;
|
2023-04-12 13:53:55 +02:00
|
|
|
|
|
2023-09-11 11:59:33 +02:00
|
|
|
|
namespace CodexPlugin
|
2023-04-12 13:53:55 +02:00
|
|
|
|
{
|
2023-09-13 16:06:05 +02:00
|
|
|
|
public class CodexContainerRecipe : ContainerRecipeFactory
|
2023-04-12 13:53:55 +02:00
|
|
|
|
{
|
2023-09-19 10:24:43 +02:00
|
|
|
|
private readonly MarketplaceStarter marketplaceStarter = new MarketplaceStarter();
|
|
|
|
|
|
2024-03-25 10:17:32 +01:00
|
|
|
|
private const string DefaultDockerImage = "codexstorage/nim-codex:sha-c219a5f-dist-tests";
|
2023-10-19 11:12:08 +02:00
|
|
|
|
public const string ApiPortTag = "codex_api_port";
|
|
|
|
|
public const string ListenPortTag = "codex_listen_port";
|
|
|
|
|
public const string MetricsPortTag = "codex_metrics_port";
|
|
|
|
|
public const string DiscoveryPortTag = "codex_discovery_port";
|
2023-04-13 14:36:17 +02:00
|
|
|
|
|
2023-09-04 10:08:34 +03:00
|
|
|
|
// Used by tests for time-constraint assertions.
|
2023-06-07 08:30:10 +02:00
|
|
|
|
public static readonly TimeSpan MaxUploadTimePerMegabyte = TimeSpan.FromSeconds(2.0);
|
|
|
|
|
public static readonly TimeSpan MaxDownloadTimePerMegabyte = TimeSpan.FromSeconds(2.0);
|
|
|
|
|
|
2023-08-07 15:51:44 +02:00
|
|
|
|
public override string AppName => "codex";
|
2023-09-28 11:31:09 +02:00
|
|
|
|
public override string Image => GetDockerImage();
|
2023-09-14 15:17:30 +10:00
|
|
|
|
|
2023-09-28 11:31:09 +02:00
|
|
|
|
public static string DockerImageOverride { get; set; } = string.Empty;
|
2023-04-12 13:53:55 +02:00
|
|
|
|
|
2023-09-13 16:06:05 +02:00
|
|
|
|
protected override void Initialize(StartupConfig startupConfig)
|
2023-04-12 13:53:55 +02:00
|
|
|
|
{
|
2023-09-21 11:07:27 +02:00
|
|
|
|
SetResourcesRequest(milliCPUs: 100, memory: 100.MB());
|
2023-11-07 09:25:51 +01:00
|
|
|
|
//SetResourceLimits(milliCPUs: 4000, memory: 12.GB());
|
2023-09-18 15:45:21 +02:00
|
|
|
|
|
2023-11-27 19:06:04 +02:00
|
|
|
|
SetSchedulingAffinity(notIn: "false");
|
2023-11-23 14:50:54 +01:00
|
|
|
|
SetSystemCriticalPriority();
|
2023-11-14 10:16:00 +01:00
|
|
|
|
|
2023-04-12 13:53:55 +02:00
|
|
|
|
var config = startupConfig.Get<CodexStartupConfig>();
|
|
|
|
|
|
2023-10-23 11:30:54 +02:00
|
|
|
|
var apiPort = CreateApiPort(config, ApiPortTag);
|
|
|
|
|
AddEnvVar("CODEX_API_PORT", apiPort);
|
2023-07-04 16:04:18 +02:00
|
|
|
|
AddEnvVar("CODEX_API_BINDADDR", "0.0.0.0");
|
|
|
|
|
|
2023-09-07 08:19:19 +02:00
|
|
|
|
var dataDir = $"datadir{ContainerNumber}";
|
|
|
|
|
AddEnvVar("CODEX_DATA_DIR", dataDir);
|
2023-09-07 10:37:52 +02:00
|
|
|
|
AddVolume($"codex/{dataDir}", GetVolumeCapacity(config));
|
2023-09-07 08:19:19 +02:00
|
|
|
|
|
2023-10-23 12:33:48 +02:00
|
|
|
|
var discPort = CreateDiscoveryPort(config);
|
2023-10-23 11:30:54 +02:00
|
|
|
|
AddEnvVar("CODEX_DISC_PORT", discPort);
|
2023-09-14 15:04:37 +10:00
|
|
|
|
AddEnvVar("CODEX_LOG_LEVEL", config.LogLevelWithTopics());
|
2023-07-04 16:04:18 +02:00
|
|
|
|
|
2023-10-23 12:33:48 +02:00
|
|
|
|
if (config.PublicTestNet != null)
|
2023-10-23 11:30:54 +02:00
|
|
|
|
{
|
2023-11-15 14:53:25 +01:00
|
|
|
|
// This makes the node announce itself to its public IP address.
|
2023-10-27 11:21:43 +02:00
|
|
|
|
AddEnvVar("NAT_IP_AUTO", "false");
|
2023-12-11 08:38:31 +01:00
|
|
|
|
AddEnvVar("NAT_PUBLIC_IP_AUTO", PublicIpService.Address);
|
2023-10-23 11:30:54 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// This makes the node announce itself to its local (pod) IP address.
|
|
|
|
|
AddEnvVar("NAT_IP_AUTO", "true");
|
|
|
|
|
}
|
2023-04-12 13:53:55 +02:00
|
|
|
|
|
2023-10-23 12:33:48 +02:00
|
|
|
|
var listenPort = CreateListenPort(config);
|
2023-07-04 16:04:18 +02:00
|
|
|
|
AddEnvVar("CODEX_LISTEN_ADDRS", $"/ip4/0.0.0.0/tcp/{listenPort.Number}");
|
2023-04-12 13:53:55 +02:00
|
|
|
|
|
2023-04-24 14:09:23 +02:00
|
|
|
|
if (!string.IsNullOrEmpty(config.BootstrapSpr))
|
|
|
|
|
{
|
2023-07-04 16:04:18 +02:00
|
|
|
|
AddEnvVar("CODEX_BOOTSTRAP_NODE", config.BootstrapSpr);
|
2023-04-24 14:09:23 +02:00
|
|
|
|
}
|
2023-04-12 13:53:55 +02:00
|
|
|
|
if (config.StorageQuota != null)
|
|
|
|
|
{
|
2023-07-04 16:04:18 +02:00
|
|
|
|
AddEnvVar("CODEX_STORAGE_QUOTA", config.StorageQuota.SizeInBytes.ToString()!);
|
2023-04-12 13:53:55 +02:00
|
|
|
|
}
|
2023-06-29 16:03:45 +02:00
|
|
|
|
if (config.BlockTTL != null)
|
|
|
|
|
{
|
2023-07-14 10:45:26 +02:00
|
|
|
|
AddEnvVar("CODEX_BLOCK_TTL", config.BlockTTL.ToString()!);
|
2023-06-29 16:03:45 +02:00
|
|
|
|
}
|
2023-08-14 15:51:03 +02:00
|
|
|
|
if (config.BlockMaintenanceInterval != null)
|
|
|
|
|
{
|
|
|
|
|
AddEnvVar("CODEX_BLOCK_MI", Convert.ToInt32(config.BlockMaintenanceInterval.Value.TotalSeconds).ToString());
|
|
|
|
|
}
|
2023-08-14 16:37:31 +02:00
|
|
|
|
if (config.BlockMaintenanceNumber != null)
|
|
|
|
|
{
|
|
|
|
|
AddEnvVar("CODEX_BLOCK_MN", config.BlockMaintenanceNumber.ToString()!);
|
|
|
|
|
}
|
2023-09-13 11:59:21 +02:00
|
|
|
|
if (config.MetricsEnabled)
|
|
|
|
|
{
|
2023-10-23 11:30:54 +02:00
|
|
|
|
var metricsPort = CreateApiPort(config, MetricsPortTag);
|
2023-09-13 11:59:21 +02:00
|
|
|
|
AddEnvVar("CODEX_METRICS", "true");
|
|
|
|
|
AddEnvVar("CODEX_METRICS_ADDRESS", "0.0.0.0");
|
|
|
|
|
AddEnvVar("CODEX_METRICS_PORT", metricsPort);
|
|
|
|
|
AddPodAnnotation("prometheus.io/scrape", "true");
|
|
|
|
|
AddPodAnnotation("prometheus.io/port", metricsPort.Number.ToString());
|
|
|
|
|
}
|
2023-09-11 11:59:33 +02:00
|
|
|
|
|
2023-09-14 15:17:30 +10:00
|
|
|
|
if (config.SimulateProofFailures != null)
|
2023-09-14 15:02:53 +10:00
|
|
|
|
{
|
|
|
|
|
AddEnvVar("CODEX_SIMULATE_PROOF_FAILURES", config.SimulateProofFailures.ToString()!);
|
|
|
|
|
}
|
2023-09-14 15:11:04 +10:00
|
|
|
|
|
2023-09-19 10:24:43 +02:00
|
|
|
|
if (config.MarketplaceConfig != null)
|
|
|
|
|
{
|
|
|
|
|
var mconfig = config.MarketplaceConfig;
|
2023-09-19 11:51:59 +02:00
|
|
|
|
var gethStart = mconfig.GethNode.StartResult;
|
2023-11-06 16:10:19 +01:00
|
|
|
|
var wsAddress = gethStart.Container.GetInternalAddress(GethContainerRecipe.WsPortTag);
|
2023-09-20 09:16:57 +02:00
|
|
|
|
var marketplaceAddress = mconfig.CodexContracts.Deployment.MarketplaceAddress;
|
2023-09-19 10:24:43 +02:00
|
|
|
|
|
2023-11-06 16:10:19 +01:00
|
|
|
|
AddEnvVar("CODEX_ETH_PROVIDER", $"{wsAddress.Host.Replace("http://", "ws://")}:{wsAddress.Port}");
|
2023-09-19 10:24:43 +02:00
|
|
|
|
AddEnvVar("CODEX_MARKETPLACE_ADDRESS", marketplaceAddress);
|
|
|
|
|
|
|
|
|
|
// Custom scripting in the Codex test image will write this variable to a private-key file,
|
|
|
|
|
// and pass the correct filename to Codex.
|
|
|
|
|
var mStart = marketplaceStarter.Start();
|
|
|
|
|
AddEnvVar("PRIV_KEY", mStart.PrivateKey);
|
|
|
|
|
Additional(mStart);
|
|
|
|
|
|
2024-03-13 10:18:10 +01:00
|
|
|
|
var marketplaceSetup = config.MarketplaceConfig.MarketplaceSetup;
|
|
|
|
|
SetCommandOverride(marketplaceSetup);
|
|
|
|
|
if (marketplaceSetup.IsValidator)
|
2023-09-19 10:24:43 +02:00
|
|
|
|
{
|
2023-09-14 15:04:37 +10:00
|
|
|
|
AddEnvVar("CODEX_VALIDATOR", "true");
|
2023-09-19 10:24:43 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-13 16:06:05 +02:00
|
|
|
|
|
2023-09-21 11:07:27 +02:00
|
|
|
|
if(!string.IsNullOrEmpty(config.NameOverride))
|
|
|
|
|
{
|
2023-09-14 15:02:53 +10:00
|
|
|
|
AddEnvVar("CODEX_NODENAME", config.NameOverride);
|
2023-04-14 10:51:35 +02:00
|
|
|
|
}
|
2023-04-12 13:53:55 +02:00
|
|
|
|
}
|
2023-06-22 14:37:37 +02:00
|
|
|
|
|
2024-03-13 10:18:10 +01:00
|
|
|
|
private void SetCommandOverride(MarketplaceSetup ms)
|
|
|
|
|
{
|
2024-03-13 10:29:26 +01:00
|
|
|
|
if (ms.IsStorageNode)
|
2024-03-13 10:18:10 +01:00
|
|
|
|
{
|
2024-03-15 12:48:25 +01:00
|
|
|
|
OverrideCommand("bash", "/docker-entrypoint.sh", "codex", "persistence", "prover");
|
2024-03-13 10:18:10 +01:00
|
|
|
|
}
|
2024-03-13 10:29:26 +01:00
|
|
|
|
else
|
2024-03-13 10:18:10 +01:00
|
|
|
|
{
|
2024-03-15 12:48:25 +01:00
|
|
|
|
OverrideCommand("bash", "/docker-entrypoint.sh", "codex", "persistence");
|
2024-03-13 10:18:10 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-25 14:23:07 +02:00
|
|
|
|
private Port CreateApiPort(CodexStartupConfig config, string tag)
|
|
|
|
|
{
|
|
|
|
|
if (config.PublicTestNet == null) return AddExposedPort(tag);
|
|
|
|
|
return AddInternalPort(tag);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-23 12:33:48 +02:00
|
|
|
|
private Port CreateListenPort(CodexStartupConfig config)
|
|
|
|
|
{
|
|
|
|
|
if (config.PublicTestNet == null) return AddInternalPort(ListenPortTag);
|
|
|
|
|
|
|
|
|
|
return AddExposedPort(config.PublicTestNet.PublicListenPort, ListenPortTag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Port CreateDiscoveryPort(CodexStartupConfig config)
|
|
|
|
|
{
|
2023-10-25 14:23:07 +02:00
|
|
|
|
if (config.PublicTestNet == null) return AddInternalPort(DiscoveryPortTag, PortProtocol.UDP);
|
2023-10-23 12:33:48 +02:00
|
|
|
|
|
2023-10-25 14:23:07 +02:00
|
|
|
|
return AddExposedPort(config.PublicTestNet.PublicDiscoveryPort, DiscoveryPortTag, PortProtocol.UDP);
|
2023-10-23 12:33:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-09-08 09:39:56 +02:00
|
|
|
|
private ByteSize GetVolumeCapacity(CodexStartupConfig config)
|
2023-09-07 10:37:52 +02:00
|
|
|
|
{
|
2023-09-08 09:39:56 +02:00
|
|
|
|
if (config.StorageQuota != null) return config.StorageQuota;
|
|
|
|
|
// Default Codex quota: 8 Gb, using +20% to be safe.
|
|
|
|
|
return 8.GB().Multiply(1.2);
|
2023-09-07 10:37:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 11:12:14 +02:00
|
|
|
|
private string GetDockerImage()
|
|
|
|
|
{
|
|
|
|
|
var image = Environment.GetEnvironmentVariable("CODEXDOCKERIMAGE");
|
|
|
|
|
if (!string.IsNullOrEmpty(image)) return image;
|
2023-09-28 11:31:09 +02:00
|
|
|
|
if (!string.IsNullOrEmpty(DockerImageOverride)) return DockerImageOverride;
|
2023-07-21 09:34:37 +02:00
|
|
|
|
return DefaultDockerImage;
|
2023-07-17 11:12:14 +02:00
|
|
|
|
}
|
2023-04-12 13:53:55 +02:00
|
|
|
|
}
|
|
|
|
|
}
|