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

360 lines
14 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)
{
var eksFromAIHIT = aihitService.GetEKList(respArea.Value)?.ToList();
if (eksFromAIHIT == null)
continue;
//Удаляем текущие данные по зоне ответственности respArea
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;
}
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} -----");
}
if (!await rawDataEKService.CommitAsync())
logger.LogError($"Информация о хостах зоны ответственности {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())))
.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!.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.LogInformation($"--- Host: {host.Id}, начало синхронизации приложений ({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.Id}, добавление нового приложения 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.Id}");
isUpdated = true;
}
}
foreach (var app in host.ApplicationsInHosts)
{
var appToRemove = hostApplications.FirstOrDefault(a => a.Id == app.Id);
if (appToRemove == null)
{
//todo remove appToRemove
var obj = await appInHostService.Get().FirstOrDefaultAsync(t => t.ApplicationId == app.Id && t.HostId == host.Id);
if (obj != null)
{
logger.LogInformation($"Host: {host.Id}, удаление неактуального приложения Application {app.Application?.Name}");
appInHostService.Delete(obj);
isUpdated = true;
}
}
}
if (isUpdated && isUpdateDateModified)
host.DateModified = DateTimeOffset.UtcNow;
if (!await appInHostService.CommitAsync())
logger.LogError($"Не удалось обновить ApplicationInHost для Host: {host.Id}");
logger.LogInformation($"=== Host: {host.Id} конец синхронизации приложений ===");
}
private async Task<List<Application>> GetAndFillApplicationsAsync(RawDataEK vm)
{
logger.LogInformation($"--- Начало парсинга данных о программном обеспечении(СП, БД, ОС) из АИХ ИТ ---");
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.LogInformation($"=== Конец парсинга данных о программном обеспечении(СП, БД, ОС) из АИХ ИТ ===");
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();
//dbList.ForEach(item => item.Trim());
return dbList;
}
private List<string> GetOSFromXML(string? osField)
{
if (string.IsNullOrEmpty(osField))
return new List<string>();
var osList = osField.Split(";").Distinct().ToList();
//osList.ForEach(item => item.Trim());
return osList;
}
private async Task<Application?> CreateAppIfNotExistAsync(string appName, ApplicationTypesEnum type)//Application application)
{
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;
}
}
}