Simplify app to certificate recognition and MfApi restart only.
Remove XApi, WinRM, LocalCmd, HTTP API, TLS probe, SQL deploy model, and deploy UI. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,16 +2,8 @@ namespace ZA.CoreService.ESBCertificateManager.Models;
|
||||
|
||||
public sealed class AppSettings
|
||||
{
|
||||
public string ConnectionString { get; set; } = string.Empty;
|
||||
public bool UseOfflineSampleData { get; set; } = true;
|
||||
public string SampleTargetsPath { get; set; } = "Data/targets.sample.json";
|
||||
public string LogDirectory { get; set; } = "Logs";
|
||||
public int TlsTimeoutSeconds { get; set; } = 8;
|
||||
public int TlsRetryCount { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Verbindungskonfigurationen für Progress Sonic ESB Management Instanzen.
|
||||
/// Jeder Eintrag entspricht einer Sonic-Domain (z.B. einer Umgebung oder Tochtergesellschaft).
|
||||
/// </summary>
|
||||
public List<SonicConnection> SonicConnections { get; set; } = [];
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ public sealed class DeploymentRunResult
|
||||
public bool OverallSuccess => TargetResults.All(r => r.Success);
|
||||
public DateTimeOffset StartedAt { get; init; }
|
||||
public DateTimeOffset FinishedAt { get; init; }
|
||||
public string CertificateFilePath { get; init; } = string.Empty;
|
||||
public string CertificateFingerprint { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class TargetStepResult
|
||||
@@ -18,13 +16,8 @@ public sealed class TargetStepResult
|
||||
public bool Success { get; init; }
|
||||
public required string StatusText { get; init; }
|
||||
public string? Detail { get; init; }
|
||||
public IReadOnlyList<string> Steps { get; init; } = [];
|
||||
public DateTimeOffset StartedAt { get; init; }
|
||||
public DateTimeOffset FinishedAt { get; init; }
|
||||
public bool CopySucceeded { get; init; }
|
||||
public bool RestartSucceeded { get; init; }
|
||||
public bool TlsSucceeded { get; init; }
|
||||
public string? ObservedFingerprint { get; init; }
|
||||
}
|
||||
|
||||
public sealed class ValidationIssue
|
||||
@@ -38,3 +31,5 @@ public sealed class PreflightValidationResult
|
||||
public bool IsValid => Issues.Count == 0;
|
||||
public List<ValidationIssue> Issues { get; } = [];
|
||||
}
|
||||
|
||||
public readonly record struct TargetProgressUpdate(int TargetId, string StatusText, bool? SuccessHint);
|
||||
|
||||
@@ -4,64 +4,9 @@ public sealed class DeploymentTarget
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public required string Name { get; init; }
|
||||
public required string Environment { get; init; }
|
||||
public string Environment { get; init; } = "TEST";
|
||||
public bool IsActive { get; init; } = true;
|
||||
public required string TargetDirectory { get; init; }
|
||||
public required string CertificateFileName { get; init; }
|
||||
|
||||
/// <summary>Name des Sonic-ESB-Containers (z.B. "sonic-container-a").</summary>
|
||||
public string ContainerName { get; init; } = string.Empty;
|
||||
|
||||
public RestartType RestartType { get; init; } = RestartType.None;
|
||||
|
||||
// --- Command-basierter Neustart ---
|
||||
public string RestartCommand { get; init; } = string.Empty;
|
||||
public string RestartArguments { get; init; } = string.Empty;
|
||||
public int RestartTimeoutSeconds { get; init; } = 60;
|
||||
|
||||
// --- Sonic-ESB-Management-Neustart ---
|
||||
/// <summary>
|
||||
/// Referenz auf den Namen einer <see cref="SonicConnection"/> in AppSettings.
|
||||
/// Pflichtfeld bei RestartType = SonicContainer oder SonicContainerWithXapi.
|
||||
/// </summary>
|
||||
public string SonicConnectionName { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Pfad zur XApi-Ressourcendatei (.xml/.zip), die vor dem Neustart importiert wird.
|
||||
/// Pflichtfeld bei RestartType = SonicContainerWithXapi.
|
||||
/// </summary>
|
||||
public string XapiSourcePath { get; init; } = string.Empty;
|
||||
|
||||
// --- TLS-Probe nach Deployment ---
|
||||
public string TlsHost { get; init; } = string.Empty;
|
||||
public int? TlsPort { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Hostname, der im TLS-Handshake als ServerName (SNI) verwendet wird.
|
||||
/// Wichtig wenn TlsHost eine IP-Adresse ist, das Zertifikat aber einen DNS-Namen trägt.
|
||||
/// Ist leer, wird TlsHost als ServerName verwendet.
|
||||
/// </summary>
|
||||
public string TlsServerName { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Erwarteter SHA-256-Fingerprint des Zertifikats nach dem Deployment (ohne Trennzeichen).
|
||||
/// Wenn gesetzt, schlägt der TLS-Probe fehl wenn der Fingerprint abweicht.
|
||||
/// </summary>
|
||||
public string? ExpectedFingerprint { get; init; }
|
||||
|
||||
public int SortOrder { get; init; }
|
||||
}
|
||||
|
||||
public enum RestartType
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>Neustart über einen lokalen Betriebssystem-Prozess (RestartCommand).</summary>
|
||||
Command = 1,
|
||||
|
||||
/// <summary>Container-Neustart wie in der Sonic Management Console (stop/startcontainer bzw. SMC-API).</summary>
|
||||
SonicContainer = 2,
|
||||
|
||||
/// <summary>XApi-Ressourcen importieren und danach Container neu starten (Sonic ESB).</summary>
|
||||
SonicContainerWithXapi = 3
|
||||
}
|
||||
|
||||
@@ -1,398 +1,22 @@
|
||||
namespace ZA.CoreService.ESBCertificateManager.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Verbindungskonfiguration für eine Progress Sonic ESB Management Instanz.
|
||||
/// Name = Verbindungs-Alias (hier oft gleich ContainerName, z.B. "DE-Test").
|
||||
/// DomainName = Sonic-Domain (z.B. "proalpha-test").
|
||||
/// Container wird in KnownContainers / DeploymentTarget.ContainerName geführt (z.B. "DE-Test").
|
||||
/// SMC-/Domain-Manager-Verbindung für MfApi-Neustart.
|
||||
/// Name = Alias (z.B. DE-Test), ContainerName separat (z.B. ct-ZADBService).
|
||||
/// </summary>
|
||||
public sealed class SonicConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// Alias der Verbindung; referenziert von <see cref="DeploymentTarget.SonicConnectionName"/>.
|
||||
/// </summary>
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>Sonic-Domain, z.B. "proalpha-test" (nicht der Containername).</summary>
|
||||
public required string DomainName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Dieselbe Broker-/Management-URL wie in der Sonic Management Console (SMC),
|
||||
/// z.B. "tcp://dekun-painwbdet:13070". Keine separate Domain-Console nötig.
|
||||
/// </summary>
|
||||
public required string ConnectionUrl { get; init; }
|
||||
|
||||
/// <summary>Login wie in der Sonic Management Console (nicht für WinRM).</summary>
|
||||
public required string Username { get; init; }
|
||||
|
||||
/// <summary>Passwort wie in der Sonic Management Console (nicht für WinRM).</summary>
|
||||
public required string Password { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Windows-Konto für WinRM (<c>Invoke-Command -Credential</c>).
|
||||
/// Leer = aktueller Prozess-Benutzer ohne explizite Credentials.
|
||||
/// Nicht mit <see cref="Username"/>/<see cref="Password"/> (Sonic SMC) verwechseln.
|
||||
/// </summary>
|
||||
public string WinRmUsername { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>Windows-Passwort für WinRM; nur relevant wenn <see cref="WinRmUsername"/> gesetzt ist.</summary>
|
||||
public string WinRmPassword { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// MfApi = Sonic MF Management Runtime API über ConnectionUrl + SMC-Logins (Standard);
|
||||
/// WinRm / LocalCmd = optionaler Fallback über stopcontainer/startcontainer;
|
||||
/// HttpApi = REST (falls vorhanden).
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Standard: MfApi = Management Application API (wie SMC):
|
||||
/// JMSConnectorClient + MFProxyFactory.createAgentProxy + IAgentProxy.restart.
|
||||
/// Laut CX-Messenger-Doku-Index: Docs2017/api/mgmt_api (nicht stopcontainer.bat).
|
||||
/// LocalCmd nur wenn Server-Scripts existieren (bei reiner SMC oft nicht der Fall).
|
||||
/// </summary>
|
||||
public SonicManagementMode ManagementMode { get; init; } = SonicManagementMode.MfApi;
|
||||
|
||||
/// <summary>
|
||||
/// Effektiver Modus: bei WinRm und lokalem ConnectionUrl-Host wird LocalCmd erzwungen.
|
||||
/// MfApi bleibt unverändert (nutzt Domain-Manager-Verbindung).
|
||||
/// </summary>
|
||||
public SonicManagementMode EffectiveManagementMode
|
||||
=> ManagementMode == SonicManagementMode.WinRm && IsConnectionHostLocal(ConnectionUrl)
|
||||
? SonicManagementMode.LocalCmd
|
||||
: ManagementMode;
|
||||
|
||||
/// <summary>True wenn WinRm konfiguriert war, aber wegen lokalem Host auf LocalCmd umgestellt wurde.</summary>
|
||||
public bool IsLocalCmdAutoForced
|
||||
=> ManagementMode == SonicManagementMode.WinRm
|
||||
&& EffectiveManagementMode == SonicManagementMode.LocalCmd;
|
||||
|
||||
/// <summary>Anzeigetext für UI (inkl. Auto-Erkennung).</summary>
|
||||
public string ManagementModeDisplay
|
||||
=> IsLocalCmdAutoForced
|
||||
? "LocalCmd (Host lokal erkannt)"
|
||||
: EffectiveManagementMode switch
|
||||
{
|
||||
SonicManagementMode.MfApi => "MfApi (SMC Management Application API)",
|
||||
SonicManagementMode.LocalCmd => "LocalCmd (nur wenn stopcontainer.bat existiert)",
|
||||
_ => EffectiveManagementMode.ToString()
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// True wenn der Host aus ConnectionUrl dieser Maschine entspricht
|
||||
/// (localhost / 127.0.0.1 / ::1 / Computername).
|
||||
/// </summary>
|
||||
public static bool IsConnectionHostLocal(string? connectionUrl)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(connectionUrl))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string host;
|
||||
try
|
||||
{
|
||||
host = new Uri(connectionUrl).Host;
|
||||
}
|
||||
catch
|
||||
{
|
||||
host = connectionUrl.Trim();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (host.Equals("localhost", StringComparison.OrdinalIgnoreCase)
|
||||
|| host.Equals("127.0.0.1", StringComparison.OrdinalIgnoreCase)
|
||||
|| host.Equals("::1", StringComparison.OrdinalIgnoreCase)
|
||||
|| host.Equals("[::1]", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
string machine = Environment.MachineName;
|
||||
if (host.Equals(machine, StringComparison.OrdinalIgnoreCase)
|
||||
|| host.StartsWith(machine + ".", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string dnsName = System.Net.Dns.GetHostName();
|
||||
if (!string.IsNullOrWhiteSpace(dnsName)
|
||||
&& (host.Equals(dnsName, StringComparison.OrdinalIgnoreCase)
|
||||
|| host.StartsWith(dnsName + ".", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// DNS optional
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sonic-/MQ-/ESB-Installationsroot, z.B. "C:\Sonic\MQ10.0" (Client-JARs oft unter lib).
|
||||
/// Bei ESB-Home: ggf. MfClientLibPath auf MQ\lib setzen.
|
||||
/// </summary>
|
||||
public string SonicHome { get; init; } = @"C:\Sonic\MQ10.0";
|
||||
|
||||
/// <summary>
|
||||
/// Optional: JRE/JDK-Home (z.B. C:\Sonic\MQ10.0\jre) oder Pfad zu java.exe.
|
||||
/// Leer = automatische Suche (JAVA_HOME/JRE_HOME, setenv.bat, rekursiv unter SonicHome, Registry, …).
|
||||
/// </summary>
|
||||
public string SonicHome { get; init; } = @"C:\DEV\MQ10.0";
|
||||
public string JavaHome { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Optionaler direkter Pfad zu java.exe (überschreibt JavaHome wenn gesetzt).
|
||||
/// </summary>
|
||||
public string JavaPath { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Optionaler Pfad zu Sonic-Client-JARs für MfApi (mgmt_client.jar etc.).
|
||||
/// Leer = SonicHome\lib, MQ_HOME\lib, ESB_HOME\lib bzw. nested MQ*/lib.
|
||||
/// </summary>
|
||||
public string MfClientLibPath { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Container-Namen (kurz), z.B. ["DE-Test"]. Nicht die Domain.
|
||||
/// </summary>
|
||||
public List<string> KnownContainers { get; init; } = [];
|
||||
|
||||
public int ManagementHttpPort { get; init; } = 8080;
|
||||
public string ApiBasePath { get; init; } = "/api/v1";
|
||||
public string ContainerListPath { get; init; } = string.Empty;
|
||||
public string ContainerRestartPath { get; init; } = string.Empty;
|
||||
public string ContainerStopPath { get; init; } = string.Empty;
|
||||
public string ContainerStartPath { get; init; } = string.Empty;
|
||||
|
||||
public int WinRmPort { get; init; } = 5985;
|
||||
public string WinRmRestartScript { get; init; } = string.Empty;
|
||||
public string WinRmContainerListScript { get; init; } = string.Empty;
|
||||
public string WinRmXapiImportScript { get; init; } = string.Empty;
|
||||
|
||||
public int TimeoutSeconds { get; init; } = 120;
|
||||
public int PostRestartDelaySeconds { get; init; } = 20;
|
||||
|
||||
public string ResolveRestartScript()
|
||||
=> string.IsNullOrWhiteSpace(WinRmRestartScript)
|
||||
? DefaultRestartScript
|
||||
: WinRmRestartScript;
|
||||
|
||||
public string ResolveContainerListScript()
|
||||
=> string.IsNullOrWhiteSpace(WinRmContainerListScript)
|
||||
? DefaultContainerListScript
|
||||
: WinRmContainerListScript;
|
||||
|
||||
/// <summary>
|
||||
/// Offizieller MF-Container-Neustart laut Aurea CX Messenger Doku:
|
||||
/// SonicHome\bin\stopcontainer.bat Domain.Container
|
||||
/// SonicHome\bin\startcontainer.bat Domain.Container
|
||||
/// Danach Prozess-Verifikation (alte PIDs weg, neue PIDs da).
|
||||
/// </summary>
|
||||
public const string DefaultRestartScript =
|
||||
"""
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$sonicHome = '{sonicHome}'
|
||||
$domain = '{domain}'
|
||||
$container = '{container}'
|
||||
|
||||
$bin = Join-Path $sonicHome 'bin'
|
||||
$stopBat = Join-Path $bin 'stopcontainer.bat'
|
||||
$startBat = Join-Path $bin 'startcontainer.bat'
|
||||
|
||||
# Kurzname = Container (z.B. DE-Test), Full = Domain.Container (z.B. proalpha-test.DE-Test)
|
||||
$shortName = if ($container -like '*.*') { ($container -split '\.', 2)[1] } else { $container }
|
||||
$fullName = if ($container -like '*.*') { $container } else { "$domain.$container" }
|
||||
$markers = @($shortName, $fullName, "$domain.$shortName") | Select-Object -Unique
|
||||
|
||||
function Get-ContainerPids {
|
||||
$pids = @()
|
||||
Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
||||
Where-Object {
|
||||
$cmd = $_.CommandLine
|
||||
if (-not $cmd) { return $false }
|
||||
if ($_.Name -notmatch 'java|javaw|sonic') { return $false }
|
||||
foreach ($m in $markers) {
|
||||
if ($cmd -like "*$m*") { return $true }
|
||||
}
|
||||
return $false
|
||||
} |
|
||||
ForEach-Object { $pids += [int]$_.ProcessId }
|
||||
return @($pids | Select-Object -Unique)
|
||||
}
|
||||
|
||||
function Wait-PidsGone([int[]]$pids, [int]$seconds) {
|
||||
$deadline = (Get-Date).AddSeconds($seconds)
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
$alive = @($pids | Where-Object { Get-Process -Id $_ -ErrorAction SilentlyContinue })
|
||||
if ($alive.Count -eq 0) { return $true }
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Wait-NewPids([int[]]$oldPids, [int]$seconds) {
|
||||
$deadline = (Get-Date).AddSeconds($seconds)
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
$now = @(Get-ContainerPids)
|
||||
$fresh = @($now | Where-Object { $oldPids -notcontains $_ })
|
||||
if ($fresh.Count -gt 0) { return ,$fresh }
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
return ,@()
|
||||
}
|
||||
|
||||
function Invoke-ContainerBat([string]$bat, [string]$name) {
|
||||
if (-not (Test-Path -LiteralPath $bat)) {
|
||||
throw "Sonic BAT fehlt: $bat (SonicHome pruefen)"
|
||||
}
|
||||
$arg = '/c "' + $bat + '" "' + $name + '"'
|
||||
$p = Start-Process -FilePath 'cmd.exe' -ArgumentList $arg -Wait -PassThru -NoNewWindow
|
||||
return [int]$p.ExitCode
|
||||
}
|
||||
|
||||
Write-Output "INFO:Domain=$domain Container=$shortName Full=$fullName"
|
||||
Write-Output "INFO:RestartVia=stopcontainer/startcontainer (MF Container)"
|
||||
$before = @(Get-ContainerPids)
|
||||
Write-Output "INFO:PIDsBefore=$($before -join ',')"
|
||||
|
||||
if ($before.Count -eq 0) {
|
||||
Write-Output "WARN:No running Java/Sonic process for '$shortName' - starting anyway"
|
||||
}
|
||||
|
||||
# 1) Offiziell: stopcontainer.bat Domain.Container (danach Kurzname als Fallback)
|
||||
$stopOk = $false
|
||||
foreach ($n in @($fullName, $shortName)) {
|
||||
Write-Output "INFO:stopcontainer $n"
|
||||
$code = Invoke-ContainerBat -bat $stopBat -name $n
|
||||
Write-Output "INFO:stopcontainer ExitCode=$code Name=$n"
|
||||
if ($code -eq 0) { $stopOk = $true; break }
|
||||
}
|
||||
if (-not $stopOk) {
|
||||
Write-Output "WARN:stopcontainer non-zero; will force-stop remaining PIDs if any"
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 3
|
||||
$still = @(Get-ContainerPids)
|
||||
|
||||
# 2) Force-Stop falls BAT den Prozess nicht beendet (sonst kein echter Restart in SMC)
|
||||
if ($still.Count -gt 0) {
|
||||
Write-Output "INFO:Force-Stop PIDs=$($still -join ',')"
|
||||
foreach ($procId in $still) {
|
||||
Stop-Process -Id $procId -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
if ($before.Count -gt 0) {
|
||||
if (-not (Wait-PidsGone -pids $before -seconds 45)) {
|
||||
throw "Container process still running after stop (PIDs=$($before -join ','))"
|
||||
}
|
||||
Write-Output "INFO:Old PIDs gone"
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 3
|
||||
|
||||
# 3) Offiziell: startcontainer.bat Domain.Container
|
||||
$started = $false
|
||||
foreach ($n in @($fullName, $shortName)) {
|
||||
Write-Output "INFO:startcontainer $n"
|
||||
$code = Invoke-ContainerBat -bat $startBat -name $n
|
||||
Write-Output "INFO:startcontainer ExitCode=$code Name=$n"
|
||||
if ($code -eq 0) { $started = $true; break }
|
||||
}
|
||||
|
||||
if (-not $started) {
|
||||
throw "startcontainer failed for $fullName / $shortName"
|
||||
}
|
||||
|
||||
$after = @(Wait-NewPids -oldPids $before -seconds 60)
|
||||
if ($after.Count -eq 0) {
|
||||
$any = @(Get-ContainerPids)
|
||||
if ($any.Count -eq 0) {
|
||||
throw "After start no process for container '$shortName'. Check SMC / SonicHome / ContainerName."
|
||||
}
|
||||
Write-Output "INFO:PIDsAfter=$($any -join ',')"
|
||||
}
|
||||
else {
|
||||
Write-Output "INFO:PIDsAfter=$($after -join ',')"
|
||||
}
|
||||
|
||||
Write-Output "OK:ContainerRestartVerified Domain=$domain Container=$shortName"
|
||||
""";
|
||||
|
||||
public const string DefaultContainerListScript =
|
||||
"""
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$sonicHome = '{sonicHome}'
|
||||
$domain = '{domain}'
|
||||
$names = New-Object System.Collections.Generic.List[string]
|
||||
|
||||
function Add-Name([string]$n) {
|
||||
if ([string]::IsNullOrWhiteSpace($n)) { return }
|
||||
$n = $n.Trim()
|
||||
if (-not $names.Contains($n)) { [void]$names.Add($n) }
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $sonicHome)) {
|
||||
Write-Output "WARN:SonicHomeNichtGefunden:$sonicHome"
|
||||
}
|
||||
else {
|
||||
Write-Output "INFO:SonicHomeOk:$sonicHome Domain=$domain"
|
||||
|
||||
Get-ChildItem -LiteralPath $sonicHome -Directory -ErrorAction SilentlyContinue |
|
||||
ForEach-Object {
|
||||
if ($_.Name -like '*.cache') {
|
||||
Add-Name ($_.Name -replace '\.cache$', '')
|
||||
}
|
||||
Get-ChildItem -LiteralPath $_.FullName -Directory -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -like '*.cache' } |
|
||||
ForEach-Object { Add-Name ($_.Name -replace '\.cache$', '') }
|
||||
}
|
||||
|
||||
Get-ChildItem -LiteralPath $sonicHome -Recurse -Filter 'container.xml' -File -ErrorAction SilentlyContinue |
|
||||
Select-Object -First 40 |
|
||||
ForEach-Object {
|
||||
Add-Name (Split-Path $_.DirectoryName -Leaf)
|
||||
}
|
||||
}
|
||||
|
||||
Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.CommandLine -match 'sonic|mf\.framework|container\.xml' } |
|
||||
ForEach-Object {
|
||||
if ($_.CommandLine -match '([A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)\.cache') {
|
||||
Add-Name $Matches[1]
|
||||
}
|
||||
elseif ($_.CommandLine -match '\\([A-Za-z0-9_\-]+)\\container\.xml') {
|
||||
Add-Name $Matches[1]
|
||||
}
|
||||
}
|
||||
|
||||
# Kurzform Domain.Container → Container
|
||||
foreach ($n in @($names.ToArray())) {
|
||||
if ($n -like '*.*') {
|
||||
$parts = $n -split '\.', 2
|
||||
if ($parts.Count -eq 2) { Add-Name $parts[1] }
|
||||
}
|
||||
}
|
||||
|
||||
if ($names.Count -eq 0) {
|
||||
Write-Output "WARN:KeineContainerGefunden Domain=$domain SonicHome=$sonicHome"
|
||||
}
|
||||
|
||||
$names | Sort-Object -Unique
|
||||
""";
|
||||
}
|
||||
|
||||
public enum SonicManagementMode
|
||||
{
|
||||
HttpApi = 0,
|
||||
WinRm = 1,
|
||||
LocalCmd = 2,
|
||||
/// <summary>Sonic MF Management API über Domain-Manager (ConnectionUrl + SMC-Credentials).</summary>
|
||||
MfApi = 3
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user