agent: unify listening and dialing with directed mutual measurements
Replace Probe with Agent across node runtime, Fleet contracts, backend state, API and storage. Report incoming sessions and outgoing link health through each Agent uplink, and retain directed link controls and retry. Update protocol fixtures and end-to-end coverage for the unified model; accept requested cancellation during the Fleet timeout test cleanup.
This commit is contained in:
1 parent
d5ebf29e57
commit
ad5efc62ff
206 files changed
+4202
-4964
No files matched your search
@@ -0,0 +1,76 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Fleet.Core;
|
||||
using Fleet.Hosting;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace MoShiro.Agent;
|
||||
|
||||
/// <summary>
|
||||
/// Native supervisor bridge: writes only fixed wake-up flags and a health beacon in tmpfs.
|
||||
/// Never downloads, installs, verifies releases, or executes commands. The root-owned host
|
||||
/// updater independently fetches and verifies its locally configured release feed.
|
||||
/// </summary>
|
||||
public sealed class OpenWrtUpdater
|
||||
{
|
||||
private readonly ConfigStore _runtime;
|
||||
private readonly string _statusPath;
|
||||
private readonly TimeProvider _time;
|
||||
private readonly INodeLog _log;
|
||||
|
||||
public OpenWrtUpdater(string runtimeDirectory, string statusPath, TimeProvider time, INodeLog log)
|
||||
{
|
||||
_runtime = new ConfigStore(runtimeDirectory);
|
||||
_statusPath = statusPath;
|
||||
_time = time;
|
||||
_log = log;
|
||||
}
|
||||
|
||||
public static OpenWrtUpdater? FromEnvironment(TimeProvider time, INodeLog log) =>
|
||||
Environment.GetEnvironmentVariable(RestartUpdater.EnvironmentVariable) == "openwrt"
|
||||
? new OpenWrtUpdater("/var/run/moshiro-agent", "/var/run/moshiro-update/status.json", time, log)
|
||||
: null;
|
||||
|
||||
public void Offer() => Signal("check.request");
|
||||
|
||||
public void RequestApply() => Signal("apply.request");
|
||||
|
||||
private void Signal(string fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
_runtime.Write(fileName, "check"u8.ToArray());
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
|
||||
{
|
||||
_log.Warn("could not signal the native updater", ("err", ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Called by the Fleet heartbeat: evidence that this version reached Backend.</summary>
|
||||
public UpdateStatus? Status()
|
||||
{
|
||||
try
|
||||
{
|
||||
var health = new OpenWrtHealth(BuildInfo.Version, Environment.ProcessId, _time.GetUtcNow().ToUnixTimeSeconds());
|
||||
_runtime.Write("health.json", JsonSerializer.SerializeToUtf8Bytes(health, AgentConfigContext.Default.OpenWrtHealth));
|
||||
if (!File.Exists(_statusPath) || new FileInfo(_statusPath).Length > 8192)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize(File.ReadAllBytes(_statusPath), MoShiroJsonContext.Default.UpdateStatus);
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or JsonException)
|
||||
{
|
||||
_log.Warn("could not read native update status", ("err", ex.Message));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record OpenWrtHealth(
|
||||
[property: JsonPropertyName("version")] string Version,
|
||||
[property: JsonPropertyName("pid")] int Pid,
|
||||
[property: JsonPropertyName("at")] long At);
|
||||
Reference in new issue
Block a user