Files
parr_api/PARR.AIHIT/AIHIT/Syncher.cs

369 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.AIHIT.Services;
using PARR.DAL.Contracts;
using PARR.DAL.Extensions;
using PARR.DAL.Models;
using PARR.DAL.Models.AIHIT;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.AIHIT;
using System.Text;
namespace PARR.AIHIT
{
internal class Syncher : ISyncher
{
private readonly ILogger<Syncher> logger;
private readonly IHostService hostService;
private readonly IMapper mapper;
private readonly IApplicationService appService;
private readonly IApplicationTypeService appTypeService;
private readonly IApplicationInHostService appInHostService;
private readonly IRawDataEKService rawDataEKService;
private readonly ISettingService settingService;
private readonly IAIHITService aihitService;
public List<ApplicationType> AppTypes { get; private set; } = new List<ApplicationType>();
public Syncher(
ILogger<Syncher> logger,
IHostService hostService,
IMapper mapper,
IApplicationService appService,
IApplicationTypeService appTypeService,
IApplicationInHostService appInHostService,
IRawDataEKService rawDataEKService,
ISettingService settingService,
IAIHITService aihitService
)
{
this.hostService = hostService;
this.mapper = mapper;
this.appService = appService;
this.appTypeService = appTypeService;
this.appInHostService = appInHostService;
this.rawDataEKService = rawDataEKService;
this.settingService = settingService;
this.aihitService = aihitService;
this.logger = logger;
}
private async Task GetAppTypesAsync()
{
AppTypes = await appTypeService.Get().ToListAsync();
}
public async Task InvokeFromDatabase()
{
await GetAppTypesAsync();
//Получаем зоны ответственности из БД
var respAreas = await settingService.Get()
.Where(ra => ra.Group == AIHTITSettings.RespAreaGroupName)
.ToListAsync();
#if !DEBUG
//Запускаем хранимую процедуру в АИХ ИТ и складываем в таблицу RawDataEKs, предварительно почистив старые данные
foreach (var respArea in respAreas)
{
logger.LogDebug($"-= Получение данных об ЭК зоны ответственности {respArea.Name} =-");
var eksFromAIHIT = aihitService.GetEKList(respArea.Value)?.ToList();
if (eksFromAIHIT == null)
continue;
//Удаляем текущие данные по зоне ответственности respArea
logger.LogDebug($"-= Удаление существующих данных об ЭК зоны ответственности {respArea.Name} =-");
var toDelete = rawDataEKService.Get().Where(rd => rd.ResponseArea == respArea.Value).ToList();
toDelete.ForEach(d => rawDataEKService.Delete(d));
if(!await rawDataEKService.CommitAsync())
{
logger.LogError($"Не удалось создать удалить записи в rawDataEK зоны ответственности {respArea.Name}");
continue;
}
logger.LogDebug($"-= Создание новых записей об ЭК зоны ответственности {respArea.Name} =-");
foreach (var ek in eksFromAIHIT)
{
// создаем
var mappedEK = mapper.Map<RawDataEK>(ek);
mappedEK.Id = Guid.NewGuid();
mappedEK.DateCreated = DateTimeOffset.UtcNow;
//if (!await rawDataEKService.CreateAsync(mappedEK) || !await rawDataEKService.CommitAsync())
if (!await rawDataEKService.CreateAsync(mappedEK))
{
logger.LogError($"Не удалось создать запись rawDataEK {mappedEK.ShortName}({mappedEK.IP})");
continue;
}
else
logger.LogInformation($"Создана запись rawDataEK {mappedEK.ShortName}({mappedEK.IP}), зона ответственности {respArea.Name}");
}
logger.LogDebug($"-= Запись в базу данных записей об ЭК зоны ответственности {respArea.Name} ");
if (!await rawDataEKService.CommitAsync())
logger.LogError($"Информация о хостах зоны ответственности {respArea.Name} не записана ");
logger.LogDebug($"-= Конец синхронизации данных об ЭК зоны ответственности {respArea.Name} =-");
}
#endif
//Разбираем сырые данные
//Получаем интересующие статусы ЭК
var statusList = await settingService.Get()
.Where(s => s.Group == AIHTITSettings.StatusGroupName)
.Select(s => s.Value.Trim())
.ToListAsync();
if (statusList == null || statusList.Count == 0)
return;
//Берём только активные ЭК
var eks = await rawDataEKService.Get()
.Where(e => e.IsActive == "t" && (e.Status != null && statusList.Contains(e.Status.Trim())) && e.EKFindCode.StartsWith("ВРТ-"))
.ToListAsync();
foreach (var ek in eks)
{
if (ek.IP == null)
continue;
var foundHost = await hostService.GetHostWithAppsAsync(ek.IP);
var mappedHost = mapper.Map<Host>(ek);
//TODO Валидация по внешним связям
var hostApplications = await GetAndFillApplicationsAsync(ek);
if (foundHost == null)
{
// создаем
if (!await hostService.CreateAsync(mappedHost) || !await hostService.CommitAsync())
{
logger.LogError($"Не удалось создать узел {mappedHost.IP}");
continue;
}
else
logger.LogInformation($"----- Создан Host: {mappedHost.Id} -----");
// Синхронизация Applications
await SyncApplicationAndHostAsync(foundHost, hostApplications);
}
else
{
// обновляем
var isChanged = false;
if (!foundHost.EkStatusCode!.Equals(mappedHost.EkStatusCode))
{
foundHost.EkStatusCode = mappedHost.EkStatusCode;
isChanged = true;
}
else if (mappedHost.WorkGroup != null && (foundHost.WorkGroup == null || !foundHost.WorkGroup!.Equals(mappedHost.WorkGroup)))
{
foundHost.WorkGroup = mappedHost.WorkGroup;
isChanged = true;
}
if (isChanged)
{
foundHost.DateModified = DateTimeOffset.UtcNow;
if (!await hostService.CommitAsync())
logger.LogError($"Не удалось обновить узел {mappedHost.IP}");
else
logger.LogInformation($"Обновлён Host: {mappedHost.Id}");
}
// Синхронизация Applications
await SyncApplicationAndHostAsync(foundHost, hostApplications, true);
}
}
}
private async Task SyncApplicationAndHostAsync(Host? host, List<Application> hostApplications, bool isUpdateDateModified = false)
{
var isUpdated = false;
if (host == null)
return;
logger.LogDebug($"Host: {host.Ek}({host.IP}), начало синхронизации приложений ({hostApplications.Count()}) ");
foreach (var changedHostApp in hostApplications)
{
var exist = host.ApplicationsInHosts.FirstOrDefault(a => a.ApplicationId == changedHostApp.Id);
if (exist == null)
{
//add
logger.LogInformation($"Host: {host.Ek}({host.IP}), добавление нового приложения Application {changedHostApp.Name}");
var newAppHost = new ApplicationInHost { Id = Guid.NewGuid(), ApplicationId = changedHostApp.Id, HostId = host.Id };
if (!await appInHostService.CreateAsync(newAppHost))
logger.LogError($"Не удалось создать ApplicationInHost {changedHostApp.Name}, host: {host.Ek}({host.IP})");
isUpdated = true;
}
}
foreach (var app in host.ApplicationsInHosts)
{
var appToRemove = hostApplications.FirstOrDefault(a => a.Id == app.ApplicationId);
if (appToRemove == null)
{
//todo remove appToRemove
var obj = await appInHostService.Get().FirstOrDefaultAsync(t => t.ApplicationId == app.ApplicationId && t.HostId == host.Id);
if (obj != null)
{
logger.LogInformation($"Host: {host.Ek}({host.IP}), удаление неактуального приложения Application {app.Application?.Name}");
appInHostService.Delete(obj);
if (!await hostService.CommitAsync())
logger.LogError($"Не удалось удалить Application {app.Application?.Name} узла {host.Ek}({host.IP})");
isUpdated = true;
}
}
}
if (isUpdated && isUpdateDateModified)
host.DateModified = DateTimeOffset.UtcNow;
if (!await appInHostService.CommitAsync())
logger.LogError($"Не удалось обновить ApplicationInHost для Host: {host.Ek}({host.IP})");
logger.LogDebug($"Host: {host.Ek}({host.IP} конец синхронизации приложений");
}
private async Task<List<Application>> GetAndFillApplicationsAsync(RawDataEK vm)
{
//logger.LogDebug($"Начало парсинга данных о программном обеспечении(СП, БД, ОС) из АИХ ИТ");
var applications = new List<Application>();
if (vm.APPType != null)
{
var appList = vm.APPType.Split(new char[] { ',', ';' }).Distinct().ToList();
foreach (var app in appList)
{
var created = await CreateAppIfNotExistAsync(app, ApplicationTypesEnum.APP);
if (created != null)
applications.Add(created);
}
}
if (vm.DBType != null)
{
var appList = vm.DBType.Split(new char[] { ',', ';' }).Distinct().ToList();
foreach (var app in appList)
{
var created = await CreateAppIfNotExistAsync(app, ApplicationTypesEnum.DB);
if (created != null)
applications.Add(created);
}
}
if (vm.OSType != null)
{
var appList = vm.OSType.Split(new char[] { ',', ';' }).Distinct().ToList();
foreach (var app in appList)
{
var created = await CreateAppIfNotExistAsync(app, ApplicationTypesEnum.OS);
if (created != null)
applications.Add(created);
}
}
//logger.LogDebug($"Конец парсинга данных о программном обеспечении(СП, БД, ОС) из АИХ ИТ");
return applications;
}
private List<string> GetAppFromXML(string? appField)
{
if (string.IsNullOrEmpty(appField))
return new List<string>();
var appList = appField.Split(";").Distinct().ToList();
//appList.ForEach(item => item.Trim());
return appList;
}
private List<string> GetDBFromXML(string? dbField)
{
if (string.IsNullOrEmpty(dbField))
return new List<string>();
var dbList = dbField.Split(";").Distinct().ToList();
return dbList;
}
private List<string> GetOSFromXML(string? osField)
{
if (string.IsNullOrEmpty(osField))
return new List<string>();
var osList = osField.Split(";").Distinct().ToList();
return osList;
}
private async Task<Application?> CreateAppIfNotExistAsync(string appName, ApplicationTypesEnum type)
{
if (string.IsNullOrEmpty(appName) || string.IsNullOrWhiteSpace(appName)) return null;
var existApp = await appService.GetByNameAsync(appName);
if (existApp != null)
return existApp;
//Создаем
var appType = GetAppTypeByName(type);
if (appType == null)
{
logger.LogError($"Не удалось создать запись в таблице Applications: {appName}, так как не получил AppType: {type.ToString()}");
return null;
}
var app = new Application
{
Id = Guid.NewGuid(),
Name = appName.Trim(),
ApplicationTypeId = appType.Id
};
if (!await appService.CreateAsync(app) || !await appService.CommitAsync())
logger.LogError($"Не удалось создать запись в таблице Application: {appName}, {app.ToJson()}");
else
logger.LogInformation($"Создана запись а таблице Application: {appName}, {app.ToJson()}");
return await appService.GetAsync(app.Id);
}
private ApplicationType? GetAppTypeByName(ApplicationTypesEnum type)
{
var existType = AppTypes.FirstOrDefault(t => t.Name == type.ToString());
if (existType == null)
logger.LogError($"Не найден AppType: {type}");
return existType;
}
private static string EncodeString(string str)
{
byte[] bStr = Encoding.GetEncoding("koi8r").GetBytes(str);
Encoding encoding = Encoding.GetEncoding("koi8r");
str = encoding.GetString(bStr, 0, bStr.Length);
return str;
}
}
}