using ZA.CoreService.ESBCertificateManager.Models;
namespace ZA.CoreService.ESBCertificateManager.Services;
///
/// Sonic MfApi (wie SMC-Neustart) – ohne WinRM/HTTP/XApi.
///
public sealed class SonicManagementClient : IDisposable
{
private readonly SonicConnection _connection;
private readonly SonicMfApiExecutor _mfApi;
public SonicManagementClient(SonicConnection connection)
{
_connection = connection;
_mfApi = new SonicMfApiExecutor(connection);
}
public async Task<(bool Success, string? Error, string? ResolvedPath)> CheckConnectionAsync(
CancellationToken cancellationToken = default)
{
(bool ok, string? error) = await _mfApi.TestConnectionAsync(cancellationToken);
if (ok)
{
return (true, null, $"MfApi {_connection.ConnectionUrl} Domain={_connection.DomainName}");
}
if (_connection.KnownContainers.Count > 0
&& await IsTcpReachableAsync(_connection.ConnectionUrl, cancellationToken))
{
return (true, null,
$"MfApi-Ping fehlgeschlagen, KnownContainers/TCP ok. Hinweis: {Truncate(error)}");
}
return (false, error ?? "MfApi-Verbindung fehlgeschlagen", null);
}
public async Task<(bool Success, IReadOnlyList ContainerNames, string? Error)> GetContainersAsync(
CancellationToken cancellationToken = default)
{
(bool ok, IReadOnlyList names, string? error) =
await _mfApi.ListContainersAsync(cancellationToken);
if (ok && names.Count > 0)
{
return (true, names, null);
}
if (_connection.KnownContainers.Count > 0)
{
return (true, _connection.KnownContainers,
ok ? null : $"Liste leer/fehlerhaft – KnownContainers. {error}");
}
return (false, [], error ?? "Keine Container gefunden.");
}
public async Task<(bool Success, string Status, string? Detail)> RestartContainerAsync(
string containerName,
CancellationToken cancellationToken = default)
{
(bool ok, string? output, string? error) =
await _mfApi.RestartAsync(containerName, cancellationToken);
if (ok)
{
await Task.Delay(
TimeSpan.FromSeconds(Math.Clamp(_connection.PostRestartDelaySeconds, 0, 120)),
cancellationToken);
return (true, $"Container '{containerName}' neugestartet (MfApi)",
$"Domain={_connection.DomainName}; URL={_connection.ConnectionUrl}\n{output}");
}
return (false, "Neustart fehlgeschlagen (MfApi)",
$"Container '{containerName}', Domain '{_connection.DomainName}', URL {_connection.ConnectionUrl}\n" +
$"Fehler: {error}\n\n{output}");
}
private static async Task IsTcpReachableAsync(string connectionUrl, CancellationToken cancellationToken)
{
try
{
Uri uri = new(connectionUrl);
using System.Net.Sockets.TcpClient tcp = new();
using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
cts.CancelAfter(TimeSpan.FromSeconds(5));
await tcp.ConnectAsync(uri.Host, uri.Port > 0 ? uri.Port : 2506, cts.Token);
return true;
}
catch
{
return false;
}
}
private static string Truncate(string? s, int max = 180)
=> string.IsNullOrWhiteSpace(s) ? string.Empty
: s.Length <= max ? s : s[..max] + "…";
public void Dispose()
{
}
}