diff --git a/CoreAgent.Domain/Interfaces/Network/INetworkConfigCopier.cs b/CoreAgent.Domain/Interfaces/Network/INetworkConfigCopier.cs new file mode 100644 index 0000000..196723b --- /dev/null +++ b/CoreAgent.Domain/Interfaces/Network/INetworkConfigCopier.cs @@ -0,0 +1,19 @@ +using CoreAgent.Domain.Entities; +using CoreAgent.Domain.Models.Network; +using CoreAgent.Domain.Models.System; + +namespace CoreAgent.Domain.Interfaces.Network; + +/// +/// 网络配置复制器接口 +/// +public interface INetworkConfigCopier +{ + /// + /// 将配置值复制到临时目录并更新配置路径 + /// + /// 网络配置 + /// 应用设置 + /// 复制结果 + Task CopyConfigValuesToTempAsync(NetworkConfiguration networkConfig, AppSettings appSettings); +} \ No newline at end of file diff --git a/CoreAgent.Domain/Interfaces/Network/INetworkInterfaceManager.cs b/CoreAgent.Domain/Interfaces/Network/INetworkInterfaceManager.cs new file mode 100644 index 0000000..1f53994 --- /dev/null +++ b/CoreAgent.Domain/Interfaces/Network/INetworkInterfaceManager.cs @@ -0,0 +1,31 @@ +using CoreAgent.Domain.Entities; +using CoreAgent.Domain.Models.Network; + +namespace CoreAgent.Domain.Interfaces.Network; + +/// +/// 网络接口管理器接口 +/// +public interface INetworkInterfaceManager +{ + /// + /// 执行初始化命令 + /// + /// 是否为启动时的初始化 + /// 初始化结果 + Task ExecuteInitializeCommandsAsync(bool isStartup = false); + + /// + /// 启用网络接口 + /// + /// 网络配置 + /// 启用结果 + Task EnableAsync(NetworkConfiguration networkConfig); + + /// + /// 禁用网络接口 + /// + /// 网络配置键 + /// 禁用结果 + Task DisableAsync(string neConfigKey); +} \ No newline at end of file diff --git a/CoreAgent.Domain/Models/Network/NetworkConfigCopyResult.cs b/CoreAgent.Domain/Models/Network/NetworkConfigCopyResult.cs new file mode 100644 index 0000000..f53eb26 --- /dev/null +++ b/CoreAgent.Domain/Models/Network/NetworkConfigCopyResult.cs @@ -0,0 +1,34 @@ +namespace CoreAgent.Domain.Models.Network; + +/// +/// 网络配置复制结果 +/// +public class NetworkConfigCopyResult +{ + /// + /// 是否成功 + /// + public bool IsSuccess { get; } + + /// + /// 错误信息 + /// + public string ErrorMessage { get; } + + private NetworkConfigCopyResult(bool isSuccess, string errorMessage = null) + { + IsSuccess = isSuccess; + ErrorMessage = errorMessage; + } + + /// + /// 创建成功结果 + /// + public static NetworkConfigCopyResult Success() => new(true); + + /// + /// 创建失败结果 + /// + /// 错误信息 + public static NetworkConfigCopyResult Failure(string errorMessage) => new(false, errorMessage); +} \ No newline at end of file diff --git a/CoreAgent.Domain/Models/Network/NetworkInterfaceOperationResult.cs b/CoreAgent.Domain/Models/Network/NetworkInterfaceOperationResult.cs new file mode 100644 index 0000000..ba4aeb2 --- /dev/null +++ b/CoreAgent.Domain/Models/Network/NetworkInterfaceOperationResult.cs @@ -0,0 +1,34 @@ +namespace CoreAgent.Domain.Models.Network; + +/// +/// 网络接口操作结果 +/// +public class NetworkInterfaceOperationResult +{ + /// + /// 是否成功 + /// + public bool IsSuccess { get; } + + /// + /// 错误信息 + /// + public string ErrorMessage { get; } + + private NetworkInterfaceOperationResult(bool isSuccess, string errorMessage = null) + { + IsSuccess = isSuccess; + ErrorMessage = errorMessage; + } + + /// + /// 创建成功结果 + /// + public static NetworkInterfaceOperationResult Success() => new(true); + + /// + /// 创建失败结果 + /// + /// 错误信息 + public static NetworkInterfaceOperationResult Failure(string errorMessage) => new(false, errorMessage); +} \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs b/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs index 200bc4b..1b082df 100644 --- a/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs +++ b/CoreAgent.Infrastructure/Extensions/ServiceCollection/CommandServiceExtensions.cs @@ -36,7 +36,8 @@ public static class CommandServiceExtensions services.AddScoped(); // 注册网络配置器 services.AddScoped(); - + services.AddScoped(); + services.AddScoped(); // 注册网络服务 services.AddScoped(); diff --git a/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs b/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs index 8996b9a..79d1d21 100644 --- a/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs +++ b/CoreAgent.Infrastructure/Services/Network/CellularNetworkService.cs @@ -21,23 +21,30 @@ public class CellularNetworkService : ICellularNetworkService private readonly ISystemCommandExecutor _commandExecutor; private readonly INetworkConfigurationService _configService; private readonly ICellularNetworkContext _context; + private readonly INetworkConfigCopier _configCopier; + private readonly INetworkInterfaceManager _interfaceManager; private static readonly SemaphoreSlim _startLock = new(1, 1); private const int MaxConnectionAttempts = 30; private const int ConnectionCheckDelayMs = 1000; private const int LockTimeoutSeconds = 5; private const string NULL_CONFIG = "NULL"; private const string KILL_COMMAND_TEMPLATE = "ps -ef | grep {0} | grep -v grep | awk '{{print $2}}' | xargs kill -9"; + private const string COM_ADDR_TEMPLATE = "cat {0} | grep com_addr | awk -F'\"' '{{print $4}}'"; public CellularNetworkService( ILogger logger, ISystemCommandExecutor commandExecutor, INetworkConfigurationService configService, - ICellularNetworkContext context) + ICellularNetworkContext context, + INetworkConfigCopier configCopier, + INetworkInterfaceManager interfaceManager) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _commandExecutor = commandExecutor ?? throw new ArgumentNullException(nameof(commandExecutor)); _configService = configService ?? throw new ArgumentNullException(nameof(configService)); _context = context ?? throw new ArgumentNullException(nameof(context)); + _configCopier = configCopier ?? throw new ArgumentNullException(nameof(configCopier)); + _interfaceManager = interfaceManager ?? throw new ArgumentNullException(nameof(interfaceManager)); } /// @@ -163,30 +170,16 @@ public class CellularNetworkService : ICellularNetworkService } // 2. 执行初始化命令 - await ExecuteInitializeCommandsAsync(); - - // 3. 执行停止命令 - _logger.LogInformation("正在执行停止命令: {ConfigKey}", neConfigKey); - var commands = _context.GetNetworkCommandConfig(); - if (commands?.NetworkCommands != null) + var initResult = await _interfaceManager.ExecuteInitializeCommandsAsync(); + if (!initResult.IsSuccess) { - var stopCommands = commands.NetworkCommands - .Where(s => s.Type == NetworkCommandType.StopNetwork) - .ToArray(); - - foreach (var cmd in stopCommands) - { - if (!await ExecuteCommandAsync(cmd)) - { - _logger.LogWarning("停止命令执行失败: {Template}", cmd.Template); - } - } + _logger.LogWarning("执行初始化命令失败: {ErrorMessage}", initResult.ErrorMessage); } - // 4. 停止网络配置 - if (!await DisableNetworkInterfaceAsync(neConfigKey)) + var disableResult = await _interfaceManager.DisableAsync(neConfigKey); + if (!disableResult.IsSuccess) { - return CellularNetworkOperationResult.Failure("停止网络配置失败"); + return CellularNetworkOperationResult.Failure(disableResult.ErrorMessage); } // 5. 更新状态 @@ -215,414 +208,35 @@ public class CellularNetworkService : ICellularNetworkService } // 2. 执行初始化命令 - await ExecuteInitializeCommandsAsync(true); + var initResult = await _interfaceManager.ExecuteInitializeCommandsAsync(true); + if (!initResult.IsSuccess) + { + _logger.LogWarning("执行初始化命令失败: {ErrorMessage}", initResult.ErrorMessage); + } - // 3. 启动网络配置 + // 3. 复制配置值到临时目录并更新配置路径 + var copyResult = await _configCopier.CopyConfigValuesToTempAsync(config, _context.GetAppSettings()); + if (!copyResult.IsSuccess) + { + var message = $"复制配置值到临时目录失败: {copyResult.ErrorMessage}"; + _logger.LogError(message); + return CellularNetworkOperationResult.Failure(message); + } + + // 4. 启动网络配置 _logger.LogInformation("正在启动蜂窝网络配置: {ConfigKey}", key); - if (!await EnableNetworkInterfaceAsync(config)) + var enableResult = await _interfaceManager.EnableAsync(config); + if (!enableResult.IsSuccess) { - var message = $"启动网络配置失败: {key}"; + var message = $"启动网络配置失败: {enableResult.ErrorMessage}"; _logger.LogError(message); return CellularNetworkOperationResult.Failure(message); } - // 4. 更新状态 + // 5. 更新状态 var state = _context.GetNetworkState(); state.MarkAsStarted(); _logger.LogInformation("蜂窝网络配置 {ConfigKey} 启动成功", key); return CellularNetworkOperationResult.Success(state.CurrentStatus); } - - private async Task ExecuteInitializeCommandsAsync(bool bStartInit = false) - { - var commands = _context.GetNetworkCommandConfig(); - if (commands?.NetworkCommands != null) - { - var initCommands = commands.NetworkCommands - .Where(s => s.Type == NetworkCommandType.Initialize || - (bStartInit && s.Type == NetworkCommandType.PreNetworkOperation)) - .ToArray(); - - foreach (var cmd in initCommands) - { - if (!await ExecuteCommandAsync(cmd)) - { - _logger.LogWarning("初始化命令执行失败: {Template}", cmd.Template); - } - } - } - } - - private async Task ExecuteCommandAsync(CommandTemplateConfig command) - { - try - { - if (command.CanBeKilled) - { - return await KillProcessAsync(command.Template, command.Timeout); - } - - var result = await _commandExecutor.ExecuteCommandAsync(command.Template, new CancellationTokenSource(),command.Timeout); - return result.IsSuccess; - } - catch (Exception ex) - { - _logger.LogError(ex, "执行命令失败: {Template}", command.Template); - return false; - } - } - - private async Task KillProcessAsync(string template,int Timeout) - { - string killCmd = string.Format(KILL_COMMAND_TEMPLATE, template); - var result = await _commandExecutor.ExecuteCommandAsync(killCmd, new CancellationTokenSource()); - _logger.LogInformation("已终止进程: {Template}", template); - return result.IsSuccess; - } - - private async Task EnableNetworkInterfaceAsync(NetworkConfiguration networkConfig) - { - try - { - // 验证配置 - if (!ValidateConfig(networkConfig)) - { - _logger.LogError("网络配置验证失败"); - return false; - } - - // 复制配置值到临时目录并更新配置路径 - if (!CopyConfigValuesToTempAsync(networkConfig)) - { - _logger.LogError("复制配置值到临时目录失败"); - return false; - } - - var commands = _context.GetNetworkCommandConfig(); - var startCommand = commands.NetworkCommands.FirstOrDefault(s => s.Type == NetworkCommandType.NetworkOperation); - if (startCommand == null) - { - _logger.LogError("未找到启动命令配置"); - return false; - } - - // 根据配置类型执行不同的启动命令 - if (HasBothRagAndCoreConfigs(networkConfig)) - { - return await ExecuteFullConfigStartCommandAsync(startCommand, networkConfig); - } - else if (HasOnlyRagConfig(networkConfig)) - { - return await ExecuteRagOnlyStartCommandAsync(startCommand, networkConfig); - } - else if (HasOnlyCoreConfigs(networkConfig)) - { - return await ExecuteCoreOnlyStartCommandsAsync(startCommand, networkConfig); - } - - _logger.LogWarning("无有效配置,跳过启动"); - return false; - } - catch (Exception ex) - { - _logger.LogError(ex, "启动网络接口失败"); - return false; - } - } - - /// - /// 将配置值复制到临时目录并更新配置路径 - /// - private bool CopyConfigValuesToTempAsync(NetworkConfiguration networkConfig) - { - try - { - // 确保所需目录存在 - EnsureDirectoriesExist(); - - // 复制 RAG 配置文件 - if (!string.IsNullOrEmpty(networkConfig.RagConfig)) - { - if (!CopyConfigFile(networkConfig.RagConfig, _context.GetAppSettings().RanConfigDirectory, - path => networkConfig.RagConfig = path, "RAG")) - { - return false; - } - } - - // 复制核心网络配置文件和IMS配置文件 - foreach (var config in networkConfig.CoreOrImsConfigs) - { - if (!string.IsNullOrEmpty(config.CoreNetworkConfig)) - { - if (!CopyConfigFile(config.CoreNetworkConfig, _context.GetAppSettings().MmeConfigDirectory, - path => config.CoreNetworkConfig = path, "核心网络")) - { - return false; - } - } - - if (!string.IsNullOrEmpty(config.ImsConfig)) - { - if (!CopyConfigFile(config.ImsConfig, _context.GetAppSettings().MmeConfigDirectory, - path => config.ImsConfig = path, "IMS")) - { - return false; - } - } - } - - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "复制配置文件到临时目录时发生错误"); - return false; - } - } - - private void EnsureDirectoriesExist() - { - var appSettings = _context.GetAppSettings(); - if (!Directory.Exists(appSettings.TempDirectory)) - { - Directory.CreateDirectory(appSettings.TempDirectory); - } - if (!Directory.Exists(appSettings.RanConfigDirectory)) - { - Directory.CreateDirectory(appSettings.RanConfigDirectory); - } - if (!Directory.Exists(appSettings.MmeConfigDirectory)) - { - Directory.CreateDirectory(appSettings.MmeConfigDirectory); - } - } - - private bool CopyConfigFile(string sourcePath, string targetDirectory, Action updatePath, string configType) - { - var appSettings = _context.GetAppSettings(); - if (!File.Exists(sourcePath)) - { - _logger.LogError("{ConfigType}配置文件不存在: {FilePath}", configType, sourcePath); - return false; - } - - var fileName = Path.GetFileName(sourcePath); - var tempPath = Path.Combine(appSettings.TempDirectory, fileName); - - // 始终复制到临时目录 - File.Copy(sourcePath, tempPath, true); - - // 如果不在目标目录下,则复制到该目录并更新路径 - if (!sourcePath.StartsWith(targetDirectory)) - { - var targetPath = Path.Combine(targetDirectory, fileName); - File.Copy(sourcePath, targetPath, true); - updatePath(targetPath); - _logger.LogInformation("{ConfigType}配置文件已复制到目标目录: {FilePath}", configType, targetPath); - } - else - { - _logger.LogInformation("{ConfigType}配置文件已在目标目录中: {FilePath}", configType, sourcePath); - } - - return true; - } - - private bool HasBothRagAndCoreConfigs(NetworkConfiguration config) - { - return !string.IsNullOrWhiteSpace(config.RagConfig) && config.CoreOrImsConfigs.Any(); - } - - private bool HasOnlyRagConfig(NetworkConfiguration config) - { - return !string.IsNullOrWhiteSpace(config.RagConfig) && !config.CoreOrImsConfigs.Any(); - } - - private bool HasOnlyCoreConfigs(NetworkConfiguration config) - { - return string.IsNullOrWhiteSpace(config.RagConfig) && config.CoreOrImsConfigs.Any(); - } - - private async Task ExecuteFullConfigStartCommandAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) - { - if (networkConfig.CoreOrImsConfigs.Count == 1) - { - return await ExecuteSingleConfigStartCommandAsync(startCommand, networkConfig); - } - return await ExecuteMultiConfigStartCommandsAsync(startCommand, networkConfig); - } - - private async Task ExecuteRagOnlyStartCommandAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) - { - var command = string.Format(startCommand.Template, 1); - var fullCommand = $"{command} {networkConfig.RagConfig}"; - - _logger.LogInformation("执行RAG配置启动命令: {Command}", fullCommand); - var result = await _commandExecutor.ExecuteCommandAsync(fullCommand, new CancellationTokenSource()); - return result.IsSuccess; - } - - private async Task ExecuteCoreOnlyStartCommandsAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) - { - var commands = new List(); - var secondaryConfigs = networkConfig.CoreOrImsConfigs.ToArray(); - - var secondaryTasks = new List>(); - - for (int i = 0; i < secondaryConfigs.Length; i++) - { - var config = secondaryConfigs[i]; - var command = string.Format(startCommand.Template, i + 1); - var fullCommand = $"{command} {NULL_CONFIG} {config.CoreNetworkConfig} {config.ImsConfig}"; - - _logger.LogInformation("并发执行次要配置启动命令: {Command}", fullCommand); - secondaryTasks.Add(_commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource)); - } - // 等待所有次要配置命令执行完成 - var secondaryResults = await Task.WhenAll(secondaryTasks); - if (secondaryResults.Any(r => !r.IsSuccess)) - { - _logger.LogWarning("部分次要配置命令执行失败"); - return false; - } - return true; - } - - private async Task ExecuteSingleConfigStartCommandAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) - { - var config = networkConfig.CoreOrImsConfigs.First(); - var command = string.Format(startCommand.Template, 1); - var fullCommand = $"{command} {networkConfig.RagConfig} {config.CoreNetworkConfig} {config.ImsConfig}"; - - _logger.LogInformation("执行单配置启动命令: {Command}", fullCommand); - var result = await _commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource); - return result.IsSuccess; - } - - private async Task ExecuteMultiConfigStartCommandsAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) - { - var commands = new List(); - - // 添加次要配置命令 - var secondaryConfigs = networkConfig.CoreOrImsConfigs.Where(s => s.Index != 1).ToArray(); - var secondaryTasks = new List>(); - - for (int i = 0; i < secondaryConfigs.Length; i++) - { - var config = secondaryConfigs[i]; - var command = string.Format(startCommand.Template, i + 2); - var fullCommand = $"{command} NULL {config.CoreNetworkConfig} {config.ImsConfig}"; - - _logger.LogInformation("并发执行次要配置启动命令: {Command}", fullCommand); - secondaryTasks.Add(_commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource)); - } - - // 等待所有次要配置命令执行完成 - var secondaryResults = await Task.WhenAll(secondaryTasks); - if (secondaryResults.Any(r => !r.IsSuccess)) - { - _logger.LogWarning("部分次要配置命令执行失败"); - return false; - } - - // 执行主配置命令 - var primaryConfig = networkConfig.CoreOrImsConfigs.FirstOrDefault(s => s.Index == 1); - if (primaryConfig != null) - { - var primaryCommand = string.Format(startCommand.Template, 1); - var fullCommand = $"{primaryCommand} {networkConfig.RagConfig} {primaryConfig.CoreNetworkConfig} {primaryConfig.ImsConfig}"; - - _logger.LogInformation("执行主配置启动命令: {Command}", fullCommand); - var result = await _commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource); - if (!result.IsSuccess) - { - _logger.LogWarning("主配置命令执行失败: {Command}", fullCommand); - return false; - } - } - - return true; - } - - private async Task DisableNetworkInterfaceAsync(string neConfigKey) - { - var result = await _commandExecutor.ExecuteCommandAsync( - $"netsh interface cellular set interface \"{neConfigKey}\" admin=disable", - new CancellationTokenSource()); - - if (!result.IsSuccess) - { - _logger.LogError("停止网络配置失败"); - return false; - } - return true; - } - - private async Task WaitForConnectionAsync(string neConfigKey) - { - for (int i = 0; i < MaxConnectionAttempts; i++) - { - var status = await _commandExecutor.ExecuteCommandAsync( - $"netsh interface cellular show interfaces \"{neConfigKey}\"", - new CancellationTokenSource()); - - if (status.IsSuccess && status.Output.Contains("已连接", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - await Task.Delay(ConnectionCheckDelayMs); - } - - _logger.LogError("蜂窝网络连接超时"); - return false; - } - - /// - /// 验证网络配置是否有效 - /// - private bool ValidateConfig(NetworkConfiguration config) - { - if (config == null) - { - _logger.LogError("网络配置为空"); - return false; - } - - // 验证RAG配置 - if (!string.IsNullOrEmpty(config.RagConfig) && !File.Exists(config.RagConfig)) - { - _logger.LogError("RAG配置文件不存在: {FilePath}", config.RagConfig); - return false; - } - - // 验证核心网络和IMS配置 - if (config.CoreOrImsConfigs != null) - { - foreach (var coreConfig in config.CoreOrImsConfigs) - { - if (!string.IsNullOrEmpty(coreConfig.CoreNetworkConfig) && !File.Exists(coreConfig.CoreNetworkConfig)) - { - _logger.LogError("核心网络配置文件不存在: {FilePath}", coreConfig.CoreNetworkConfig); - return false; - } - - if (!string.IsNullOrEmpty(coreConfig.ImsConfig) && !File.Exists(coreConfig.ImsConfig)) - { - _logger.LogError("IMS配置文件不存在: {FilePath}", coreConfig.ImsConfig); - return false; - } - } - } - - // 验证至少有一个有效配置 - if (string.IsNullOrEmpty(config.RagConfig) && (config.CoreOrImsConfigs == null || !config.CoreOrImsConfigs.Any())) - { - _logger.LogError("没有有效的网络配置"); - return false; - } - - return true; - } } \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/Network/NetworkConfigCopier.cs b/CoreAgent.Infrastructure/Services/Network/NetworkConfigCopier.cs new file mode 100644 index 0000000..4f9342f --- /dev/null +++ b/CoreAgent.Infrastructure/Services/Network/NetworkConfigCopier.cs @@ -0,0 +1,180 @@ +using CoreAgent.Domain.Entities; +using CoreAgent.Domain.Interfaces; +using CoreAgent.Domain.Interfaces.Network; +using CoreAgent.Domain.Interfaces.System.Command; +using CoreAgent.Domain.Models.Network; +using CoreAgent.Domain.Models.System; +using Microsoft.Extensions.Logging; + +namespace CoreAgent.Infrastructure.Services.Network; + +/// +/// 网络配置复制器实现 +/// +public class NetworkConfigCopier : INetworkConfigCopier +{ + private readonly ILogger _logger; + private readonly ISystemCommandExecutor _commandExecutor; + private const string COM_ADDR_TEMPLATE = "cat {0} | grep com_addr | awk -F'\"' '{{print $4}}'"; + + public NetworkConfigCopier( + ILogger logger, + ISystemCommandExecutor commandExecutor) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _commandExecutor = commandExecutor ?? throw new ArgumentNullException(nameof(commandExecutor)); + } + + /// + /// 将配置值复制到临时目录并更新配置路径 + /// + public async Task CopyConfigValuesToTempAsync(NetworkConfiguration networkConfig, AppSettings appSettings) + { + try + { + // 确保所需目录存在 + EnsureDirectoriesExist(appSettings); + + // 复制 RAG 配置文件 + if (!string.IsNullOrEmpty(networkConfig.RagConfig)) + { + // 获取com_addr值 + var (isSuccess, comAddr, errorMessage) = await GetComAddrValueAsync(networkConfig.RagConfig, "RAG"); + if (!isSuccess) + { + return NetworkConfigCopyResult.Failure($"RAG配置文件验证失败: {errorMessage}"); + } + + if (!CopyConfigFile(networkConfig.RagConfig, appSettings.RanConfigDirectory, + path => networkConfig.RagConfig = path, "RAG")) + { + return NetworkConfigCopyResult.Failure("复制RAG配置文件失败"); + } + } + + // 复制核心网络配置文件和IMS配置文件 + foreach (var config in networkConfig.CoreOrImsConfigs) + { + if (!string.IsNullOrEmpty(config.CoreNetworkConfig)) + { + // 获取CN com_addr值 + var (isSuccess, comAddr, errorMessage) = await GetComAddrValueAsync(config.CoreNetworkConfig, "CN"); + if (!isSuccess) + { + return NetworkConfigCopyResult.Failure($"CN配置文件验证失败: {errorMessage}"); + } + + if (!CopyConfigFile(config.CoreNetworkConfig, appSettings.MmeConfigDirectory, + path => config.CoreNetworkConfig = path, "核心网络")) + { + return NetworkConfigCopyResult.Failure("复制CN配置文件失败"); + } + } + + if (!string.IsNullOrEmpty(config.ImsConfig)) + { + // 获取IMS com_addr值 + var (isSuccess, comAddr, errorMessage) = await GetComAddrValueAsync(config.ImsConfig, "IMS"); + if (!isSuccess) + { + return NetworkConfigCopyResult.Failure($"IMS配置文件验证失败: {errorMessage}"); + } + + if (!CopyConfigFile(config.ImsConfig, appSettings.MmeConfigDirectory, + path => config.ImsConfig = path, "IMS")) + { + return NetworkConfigCopyResult.Failure("复制IMS配置文件失败"); + } + } + } + + return NetworkConfigCopyResult.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "复制配置文件到临时目录时发生错误"); + return NetworkConfigCopyResult.Failure($"复制配置文件时发生错误: {ex.Message}"); + } + } + + /// + /// 获取配置文件中的com_addr值 + /// + private async Task<(bool IsSuccess, string ComAddr, string ErrorMessage)> GetComAddrValueAsync(string configPath, string configType) + { + if (string.IsNullOrEmpty(configPath)) + { + return (false, null, $"{configType}配置文件路径为空"); + } + + if (!File.Exists(configPath)) + { + return (false, null, $"{configType}配置文件不存在: {configPath}"); + } + + var result = await _commandExecutor.ExecuteCommandAsync( + string.Format(COM_ADDR_TEMPLATE, configPath), + new CancellationTokenSource()); + + if (result.IsSuccess) + { + var comAddr = result.Output.Trim(); + if (string.IsNullOrEmpty(comAddr)) + { + return (false, null, $"{configType}配置文件中未找到com_addr值"); + } + _logger.LogInformation("获取到{ConfigType} com_addr值: {ComAddr}", configType, comAddr); + return (true, comAddr, null); + } + else + { + return (false, null, $"获取{configType} com_addr值失败: {result.Error}"); + } + } + + private void EnsureDirectoriesExist(AppSettings appSettings) + { + if (!Directory.Exists(appSettings.TempDirectory)) + { + Directory.CreateDirectory(appSettings.TempDirectory); + } + if (!Directory.Exists(appSettings.RanConfigDirectory)) + { + Directory.CreateDirectory(appSettings.RanConfigDirectory); + } + if (!Directory.Exists(appSettings.MmeConfigDirectory)) + { + Directory.CreateDirectory(appSettings.MmeConfigDirectory); + } + } + + private bool CopyConfigFile(string sourcePath, string targetDirectory, Action updatePath, string configType) + { + if (!File.Exists(sourcePath)) + { + _logger.LogError("{ConfigType}配置文件不存在: {FilePath}", configType, sourcePath); + return false; + } + + var fileName = Path.GetFileName(sourcePath); + var tempPath = Path.Combine(targetDirectory, fileName); + + // 始终复制到临时目录 + File.Copy(sourcePath, tempPath, true); + + // 如果不在目标目录下,则复制到该目录并更新路径 + if (!sourcePath.StartsWith(targetDirectory)) + { + var targetPath = Path.Combine(targetDirectory, fileName); + File.Copy(sourcePath, targetPath, true); + updatePath(targetPath); + _logger.LogInformation("{ConfigType}配置文件已复制到目标目录: {FilePath}", configType, targetPath); + } + else + { + _logger.LogInformation("{ConfigType}配置文件已在目标目录中: {FilePath}", configType, sourcePath); + } + + return true; + } +} \ No newline at end of file diff --git a/CoreAgent.Infrastructure/Services/Network/NetworkInterfaceManager.cs b/CoreAgent.Infrastructure/Services/Network/NetworkInterfaceManager.cs new file mode 100644 index 0000000..e99017b --- /dev/null +++ b/CoreAgent.Infrastructure/Services/Network/NetworkInterfaceManager.cs @@ -0,0 +1,312 @@ +using CoreAgent.Domain.Entities; +using CoreAgent.Domain.Interfaces.Network; +using CoreAgent.Domain.Interfaces.System.Command; +using CoreAgent.Domain.Models.Network; +using CoreAgent.Domain.Models.System; +using Microsoft.Extensions.Logging; + +namespace CoreAgent.Infrastructure.Services.Network; + +/// +/// 网络接口管理器实现 +/// +public class NetworkInterfaceManager : INetworkInterfaceManager +{ + private readonly ILogger _logger; + private readonly ISystemCommandExecutor _commandExecutor; + private readonly ICellularNetworkContext _context; + private const string NULL_CONFIG = "NULL"; + private const string KILL_COMMAND_TEMPLATE = "ps -ef | grep {0} | grep -v grep | awk '{{print $2}}' | xargs kill -9"; + + public NetworkInterfaceManager( + ILogger logger, + ISystemCommandExecutor commandExecutor, + ICellularNetworkContext context) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _commandExecutor = commandExecutor ?? throw new ArgumentNullException(nameof(commandExecutor)); + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + /// + /// 执行初始化命令 + /// + public async Task ExecuteInitializeCommandsAsync(bool isStartup = false) + { + try + { + var commands = _context.GetNetworkCommandConfig(); + if (commands?.NetworkCommands != null) + { + var initCommands = commands.NetworkCommands + .Where(s => s.Type == NetworkCommandType.Initialize || + (isStartup && s.Type == NetworkCommandType.PreNetworkOperation)) + .ToArray(); + + foreach (var cmd in initCommands) + { + if (!await ExecuteCommandAsync(cmd)) + { + _logger.LogWarning("初始化命令执行失败: {Template}", cmd.Template); + } + } + } + return NetworkInterfaceOperationResult.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "执行初始化命令失败"); + return NetworkInterfaceOperationResult.Failure($"执行初始化命令失败: {ex.Message}"); + } + } + + /// + /// 启用网络接口 + /// + public async Task EnableAsync(NetworkConfiguration networkConfig) + { + try + { + // 验证配置 + if (!ValidateConfig(networkConfig)) + { + return NetworkInterfaceOperationResult.Failure("网络配置验证失败"); + } + + var commands = _context.GetNetworkCommandConfig(); + var startCommand = commands.NetworkCommands.FirstOrDefault(s => s.Type == NetworkCommandType.NetworkOperation); + if (startCommand == null) + { + return NetworkInterfaceOperationResult.Failure("未找到启动命令配置"); + } + + // 根据配置类型执行不同的启动命令 + if (HasBothRagAndCoreConfigs(networkConfig)) + { + return await ExecuteFullConfigStartCommandAsync(startCommand, networkConfig); + } + else if (HasOnlyRagConfig(networkConfig)) + { + return await ExecuteRagOnlyStartCommandAsync(startCommand, networkConfig); + } + else if (HasOnlyCoreConfigs(networkConfig)) + { + return await ExecuteCoreOnlyStartCommandsAsync(startCommand, networkConfig); + } + + return NetworkInterfaceOperationResult.Failure("无有效配置,跳过启动"); + } + catch (Exception ex) + { + _logger.LogError(ex, "启动网络接口失败"); + return NetworkInterfaceOperationResult.Failure($"启动网络接口失败: {ex.Message}"); + } + } + + /// + /// 禁用网络接口 + /// + public async Task DisableAsync(string neConfigKey) + { + try + { + await Task.CompletedTask.ConfigureAwait(false); + return NetworkInterfaceOperationResult.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "停止网络配置失败"); + return NetworkInterfaceOperationResult.Failure($"停止网络配置失败: {ex.Message}"); + } + } + + private async Task ExecuteCommandAsync(CommandTemplateConfig command) + { + try + { + if (command.CanBeKilled) + { + return await KillProcessAsync(command.Template, command.Timeout); + } + + var result = await _commandExecutor.ExecuteCommandAsync(command.Template, new CancellationTokenSource(), command.Timeout); + return result.IsSuccess; + } + catch (Exception ex) + { + _logger.LogError(ex, "执行命令失败: {Template}", command.Template); + return false; + } + } + + private async Task KillProcessAsync(string template, int timeout) + { + string killCmd = string.Format(KILL_COMMAND_TEMPLATE, template); + var result = await _commandExecutor.ExecuteCommandAsync(killCmd, new CancellationTokenSource()); + _logger.LogInformation("已终止进程: {Template}", template); + return result.IsSuccess; + } + + /// + /// 验证网络配置是否有效 + /// + private bool ValidateConfig(NetworkConfiguration config) + { + if (config == null) + { + _logger.LogError("网络配置为空"); + return false; + } + + // 验证RAG配置 + if (!string.IsNullOrEmpty(config.RagConfig) && !File.Exists(config.RagConfig)) + { + _logger.LogError("RAG配置文件不存在: {FilePath}", config.RagConfig); + return false; + } + + // 验证核心网络和IMS配置 + if (config.CoreOrImsConfigs != null) + { + foreach (var coreConfig in config.CoreOrImsConfigs) + { + if (!string.IsNullOrEmpty(coreConfig.CoreNetworkConfig) && !File.Exists(coreConfig.CoreNetworkConfig)) + { + _logger.LogError("核心网络配置文件不存在: {FilePath}", coreConfig.CoreNetworkConfig); + return false; + } + + if (!string.IsNullOrEmpty(coreConfig.ImsConfig) && !File.Exists(coreConfig.ImsConfig)) + { + _logger.LogError("IMS配置文件不存在: {FilePath}", coreConfig.ImsConfig); + return false; + } + } + } + + // 验证至少有一个有效配置 + if (string.IsNullOrEmpty(config.RagConfig) && (config.CoreOrImsConfigs == null || !config.CoreOrImsConfigs.Any())) + { + _logger.LogError("没有有效的网络配置"); + return false; + } + + return true; + } + + private bool HasBothRagAndCoreConfigs(NetworkConfiguration config) + { + return !string.IsNullOrWhiteSpace(config.RagConfig) && config.CoreOrImsConfigs.Any(); + } + + private bool HasOnlyRagConfig(NetworkConfiguration config) + { + return !string.IsNullOrWhiteSpace(config.RagConfig) && !config.CoreOrImsConfigs.Any(); + } + + private bool HasOnlyCoreConfigs(NetworkConfiguration config) + { + return string.IsNullOrWhiteSpace(config.RagConfig) && config.CoreOrImsConfigs.Any(); + } + + private async Task ExecuteFullConfigStartCommandAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) + { + if (networkConfig.CoreOrImsConfigs.Count == 1) + { + return await ExecuteSingleConfigStartCommandAsync(startCommand, networkConfig); + } + return await ExecuteMultiConfigStartCommandsAsync(startCommand, networkConfig); + } + + private async Task ExecuteRagOnlyStartCommandAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) + { + var command = string.Format(startCommand.Template, 1); + var fullCommand = $"{command} {networkConfig.RagConfig}"; + + _logger.LogInformation("执行RAG配置启动命令: {Command}", fullCommand); + var result = await _commandExecutor.ExecuteCommandAsync(fullCommand, new CancellationTokenSource()); + return result.IsSuccess + ? NetworkInterfaceOperationResult.Success() + : NetworkInterfaceOperationResult.Failure($"执行RAG配置启动命令失败: {result.Error}"); + } + + private async Task ExecuteCoreOnlyStartCommandsAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) + { + var commands = new List(); + var secondaryConfigs = networkConfig.CoreOrImsConfigs.ToArray(); + + var secondaryTasks = new List>(); + + for (int i = 0; i < secondaryConfigs.Length; i++) + { + var config = secondaryConfigs[i]; + var command = string.Format(startCommand.Template, i + 1); + var fullCommand = $"{command} {NULL_CONFIG} {config.CoreNetworkConfig} {config.ImsConfig}"; + + _logger.LogInformation("并发执行次要配置启动命令: {Command}", fullCommand); + secondaryTasks.Add(_commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource)); + } + + // 等待所有次要配置命令执行完成 + var secondaryResults = await Task.WhenAll(secondaryTasks); + if (secondaryResults.Any(r => !r.IsSuccess)) + { + return NetworkInterfaceOperationResult.Failure("部分次要配置命令执行失败"); + } + return NetworkInterfaceOperationResult.Success(); + } + + private async Task ExecuteSingleConfigStartCommandAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) + { + var config = networkConfig.CoreOrImsConfigs.First(); + var command = string.Format(startCommand.Template, 1); + var fullCommand = $"{command} {networkConfig.RagConfig} {config.CoreNetworkConfig} {config.ImsConfig}"; + + _logger.LogInformation("执行单配置启动命令: {Command}", fullCommand); + var result = await _commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource); + return result.IsSuccess + ? NetworkInterfaceOperationResult.Success() + : NetworkInterfaceOperationResult.Failure($"执行单配置启动命令失败: {result.Error}"); + } + + private async Task ExecuteMultiConfigStartCommandsAsync(CommandTemplateConfig startCommand, NetworkConfiguration networkConfig) + { + // 添加次要配置命令 + var secondaryConfigs = networkConfig.CoreOrImsConfigs.Where(s => s.Index != 1).ToArray(); + var secondaryTasks = new List>(); + + for (int i = 0; i < secondaryConfigs.Length; i++) + { + var config = secondaryConfigs[i]; + var command = string.Format(startCommand.Template, i + 2); + var fullCommand = $"{command} NULL {config.CoreNetworkConfig} {config.ImsConfig}"; + + _logger.LogInformation("并发执行次要配置启动命令: {Command}", fullCommand); + secondaryTasks.Add(_commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource)); + } + + // 等待所有次要配置命令执行完成 + var secondaryResults = await Task.WhenAll(secondaryTasks); + if (secondaryResults.Any(r => !r.IsSuccess)) + { + return NetworkInterfaceOperationResult.Failure("部分次要配置命令执行失败"); + } + + // 执行主配置命令 + var primaryConfig = networkConfig.CoreOrImsConfigs.FirstOrDefault(s => s.Index == 1); + if (primaryConfig != null) + { + var primaryCommand = string.Format(startCommand.Template, 1); + var fullCommand = $"{primaryCommand} {networkConfig.RagConfig} {primaryConfig.CoreNetworkConfig} {primaryConfig.ImsConfig}"; + + _logger.LogInformation("执行主配置启动命令: {Command}", fullCommand); + var result = await _commandExecutor.ExecuteCommandAsync(fullCommand, _context.TokenSource); + if (!result.IsSuccess) + { + return NetworkInterfaceOperationResult.Failure($"主配置命令执行失败: {result.Error}"); + } + } + + return NetworkInterfaceOperationResult.Success(); + } +} \ No newline at end of file