Модели Apps, Scheduler
This commit is contained in:
@@ -4,6 +4,8 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MimeKit;
|
||||
using PARR.AIHIT.Settings;
|
||||
using PARR.DAL.Contracts;
|
||||
using PARR.DAL.Extensions;
|
||||
using PARR.DAL.Models;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
using PARR.Mail.Services;
|
||||
@@ -19,31 +21,48 @@ namespace PARR.AIHIT
|
||||
private readonly SyncherSettings syncherSettings;
|
||||
private readonly IHostService hostService;
|
||||
private readonly IMapper mapper;
|
||||
private readonly IApplicationService appService;
|
||||
private readonly IApplicationTypeService appTypeService;
|
||||
private readonly IApplicationInHostService appInHostService;
|
||||
|
||||
public List<ApplicationType> AppTypes { get; private set; }
|
||||
|
||||
public Syncher(
|
||||
ILogger<Syncher> logger,
|
||||
IMailService mailService,
|
||||
SyncherSettings syncherSettings,
|
||||
IHostService hostService,
|
||||
IMapper mapper
|
||||
IMapper mapper,
|
||||
IApplicationService appService,
|
||||
IApplicationTypeService appTypeService,
|
||||
IApplicationInHostService appInHostService
|
||||
)
|
||||
{
|
||||
this.hostService = hostService;
|
||||
this.mapper = mapper;
|
||||
this.appService = appService;
|
||||
this.appTypeService = appTypeService;
|
||||
this.appInHostService = appInHostService;
|
||||
this.logger = logger;
|
||||
this.mailService = mailService;
|
||||
this.syncherSettings = syncherSettings;
|
||||
}
|
||||
|
||||
private async Task GetAppTypesAsync()
|
||||
{
|
||||
AppTypes = await appTypeService.Get().ToListAsync();
|
||||
}
|
||||
|
||||
public async Task InvokeAsync()
|
||||
{
|
||||
var hosts = await hostService.Get().ToListAsync();
|
||||
await GetAppTypesAsync();
|
||||
|
||||
var messages = await mailService.CheckMailAsync(SearchQuery.NotSeen);
|
||||
if (!messages.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var filtered = messages.Where(m => syncherSettings.IncludeAddressesArray.Any(i => m.Envelope.From.Mailboxes.First().Address == i)).ToList();
|
||||
var filtered = messages.Where(m => syncherSettings.IncludeAddressesArray.Any(i => m.Envelope.From.Mailboxes.FirstOrDefault()?.Address == i)).ToList();
|
||||
var lastMessage = filtered.OrderByDescending(f => f.Date).First();
|
||||
var attachments = await mailService.GetAttachmentsAsync(lastMessage);
|
||||
foreach (var attachment in attachments)
|
||||
@@ -54,7 +73,7 @@ namespace PARR.AIHIT
|
||||
}
|
||||
else
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
using var stream = new MemoryStream();
|
||||
((MimePart)attachment).Content.DecodeTo(stream);
|
||||
if (stream.Position > 0) stream.Position = 0;
|
||||
|
||||
@@ -71,14 +90,33 @@ namespace PARR.AIHIT
|
||||
var ip = vm?.Attributes?["IP_АДРЕС"]?.Value.Trim();
|
||||
if (ip == null) continue;
|
||||
var regionalEK = vm!.Attributes!["РЕГИОНАЛЬНЫЙ_ЭК"]!.Value.Trim();
|
||||
var eK = vm!.Attributes!["СВЯЗАННЫЙ_ЭК"]!.Value.Trim();
|
||||
if (!eK.StartsWith("ВРТ")) continue;
|
||||
var linkEK = vm!.Attributes!["СВЯЗАННЫЙ_ЭК"]!.Value.Trim();
|
||||
if (!linkEK.StartsWith("ВРТ")) continue;
|
||||
|
||||
var foundHost = await hostService.GetHostByIPAndRegionalEKAsync(ip, regionalEK);
|
||||
// var foundHost = await hostService.GetHostAsync(ip, linkEK, regionalEK);
|
||||
var foundHost = await hostService.GetHostWithAppsAsync(ip, linkEK, regionalEK);
|
||||
var mappedHost = mapper.Map<Host>(vm);
|
||||
|
||||
if (foundHost != null)
|
||||
var hostApplications = await GetAndFillApplicationsAsync(vm);
|
||||
|
||||
if (foundHost == null)
|
||||
{
|
||||
// создаем
|
||||
if (!await hostService.CreateAsync(mappedHost) || !await hostService.CommitAsync())
|
||||
{
|
||||
logger.LogError($"Не удалось создать узел {mappedHost.IP} {mappedHost.RegionalEK}");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
logger.LogInformation($"----- Создан Host: {mappedHost.Id}, {mappedHost.LinkEK} -----");
|
||||
|
||||
|
||||
// Синхронизация Applications
|
||||
await SyncApplicationAndHostAsync(foundHost, hostApplications);
|
||||
}
|
||||
else
|
||||
{
|
||||
// обновляем
|
||||
var isChanged = false;
|
||||
if (!foundHost.RegionalEK!.Equals(mappedHost.RegionalEK))
|
||||
{
|
||||
@@ -104,32 +142,33 @@ namespace PARR.AIHIT
|
||||
foundHost.Responsible = mappedHost.Responsible;
|
||||
isChanged = true;
|
||||
}
|
||||
else if (!foundHost.OS!.Equals(mappedHost.OS))
|
||||
{
|
||||
foundHost.OS = mappedHost.OS;
|
||||
isChanged = true;
|
||||
}
|
||||
else if (!foundHost.DB!.Equals(mappedHost.DB))
|
||||
{
|
||||
foundHost.DB = mappedHost.DB;
|
||||
isChanged = true;
|
||||
}
|
||||
else if (!foundHost.APP!.Equals(mappedHost.APP))
|
||||
{
|
||||
foundHost.APP = mappedHost.APP;
|
||||
isChanged = true;
|
||||
}
|
||||
foundHost.DateModified = DateTimeOffset.UtcNow; ;
|
||||
|
||||
if (isChanged && !await hostService.CommitAsync())
|
||||
logger.LogError($"Не удалось обновить узел {mappedHost.IP} {mappedHost.RegionalEK}");
|
||||
else logger.LogInformation($"Обновлён узел {mappedHost.IP} {mappedHost.RegionalEK}");
|
||||
//else if (!foundHost.OS!.Equals(mappedHost.OS))
|
||||
//{
|
||||
// foundHost.OS = mappedHost.OS;
|
||||
// isChanged = true;
|
||||
//}
|
||||
//else if (!foundHost.DB!.Equals(mappedHost.DB))
|
||||
//{
|
||||
// foundHost.DB = mappedHost.DB;
|
||||
// isChanged = true;
|
||||
//}
|
||||
//else if (!foundHost.APP!.Equals(mappedHost.APP))
|
||||
//{
|
||||
// foundHost.APP = mappedHost.APP;
|
||||
// isChanged = true;
|
||||
//}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!await hostService.CreateAsync(mappedHost) || !await hostService.CommitAsync())
|
||||
logger.LogError($"Не удалось создать узел {mappedHost.IP} {mappedHost.RegionalEK}");
|
||||
if (isChanged)
|
||||
{
|
||||
foundHost.DateModified = DateTimeOffset.UtcNow;
|
||||
if (!await hostService.CommitAsync())
|
||||
logger.LogError($"Не удалось обновить узел {mappedHost.IP} {mappedHost.RegionalEK}");
|
||||
else
|
||||
logger.LogInformation($"----- Обновлён Host: {mappedHost.Id}, {mappedHost.LinkEK} -----");
|
||||
}
|
||||
|
||||
// Синхронизация Applications
|
||||
await SyncApplicationAndHostAsync(foundHost, hostApplications, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -168,22 +207,181 @@ namespace PARR.AIHIT
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsChanged(Host host, Host mappedHost)
|
||||
private async Task SyncApplicationAndHostAsync(Host? host, List<Application> hostApplications, bool isUpdateDateModified = false)
|
||||
{
|
||||
if (host == null) return true;
|
||||
if (mappedHost == null) return true;
|
||||
if (!host.IP.Equals(mappedHost.IP)) return true;
|
||||
if (!host.RegionalEK!.Equals(mappedHost.RegionalEK)) return true;
|
||||
if (!host.LinkEK!.Equals(mappedHost.LinkEK)) return true;
|
||||
if (!host.Status!.Equals(mappedHost.Status)) return true;
|
||||
if (!host.WorkGroup!.Equals(mappedHost.WorkGroup)) return true;
|
||||
if (!host.Responsible!.Equals(mappedHost.Responsible)) return true;
|
||||
if (!host.OS!.Equals(mappedHost.OS)) return true;
|
||||
if (!host.DB!.Equals(mappedHost.DB)) return true;
|
||||
if (!host.APP!.Equals(mappedHost.APP)) return true;
|
||||
return false;
|
||||
var isUpdated = false;
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
logger.LogInformation($"--- Host: {host.Id}, {host.LinkEK} начало синхронизации приложений ({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}, {host.LinkEK} добавление нового приложения 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}, {host.LinkEK}");
|
||||
|
||||
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}, {host.LinkEK} удаление неактуального приложения 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.LinkEK}, {host.Id}");
|
||||
|
||||
logger.LogInformation($"=== Host: {host.Id}, {host.LinkEK} конец синхронизации приложений ===");
|
||||
|
||||
}
|
||||
|
||||
private async Task<List<Application>> GetAndFillApplicationsAsync(XmlNode vm)
|
||||
{
|
||||
logger.LogInformation($"--- Начало парсинга данных о программном обеспечении(СП, БД, ОС) из Xml документа от АИХ ИТ ---");
|
||||
var applications = new List<Application>();
|
||||
|
||||
//TODO GetAppFromXML(vm?.Attributes?["СП"]?.Value).ForEach(async item => await CreateAppIfNotExistAsync(item, ApplicationTypesEnum.APP));
|
||||
//GetDBFromXML(vm?.Attributes?["СУБД"]?.Value).ForEach(async item => await CreateAppIfNotExistAsync(item, ApplicationTypesEnum.DB));
|
||||
//GetOSFromXML(vm?.Attributes?["ОС"]?.Value).ForEach(async item => await CreateAppIfNotExistAsync(item, ApplicationTypesEnum.OS));
|
||||
var appList = GetAppFromXML(vm?.Attributes?["СП"]?.Value);
|
||||
foreach (var app in appList)
|
||||
{
|
||||
var created = await CreateAppIfNotExistAsync(app, ApplicationTypesEnum.APP);
|
||||
if (created != null)
|
||||
applications.Add(created);
|
||||
}
|
||||
var dbList = GetAppFromXML(vm?.Attributes?["СУБД"]?.Value);
|
||||
foreach (var db in dbList)
|
||||
{
|
||||
var created = await CreateAppIfNotExistAsync(db, ApplicationTypesEnum.DB);
|
||||
if (created != null)
|
||||
applications.Add(created);
|
||||
}
|
||||
var osList = GetAppFromXML(vm?.Attributes?["ОС"]?.Value);
|
||||
foreach (var os in appList)
|
||||
{
|
||||
var created = await CreateAppIfNotExistAsync(os, ApplicationTypesEnum.OS);
|
||||
if (created != null)
|
||||
applications.Add(created);
|
||||
}
|
||||
|
||||
logger.LogInformation($"=== Конец парсинга данных о программном обеспечении(СП, БД, ОС) из Xml документа от АИХ ИТ ===");
|
||||
|
||||
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)) return null;
|
||||
|
||||
var existApp = await appService.GetByName(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 DAL.Models.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 bool IsChanged(Host host, Host mappedHost)
|
||||
//{
|
||||
// if (host == null) return true;
|
||||
// if (mappedHost == null) return true;
|
||||
// if (!host.IP.Equals(mappedHost.IP)) return true;
|
||||
// if (!host.RegionalEK!.Equals(mappedHost.RegionalEK)) return true;
|
||||
// if (!host.LinkEK!.Equals(mappedHost.LinkEK)) return true;
|
||||
// if (!host.Status!.Equals(mappedHost.Status)) return true;
|
||||
// if (!host.WorkGroup!.Equals(mappedHost.WorkGroup)) return true;
|
||||
// if (!host.Responsible!.Equals(mappedHost.Responsible)) return true;
|
||||
// return false;
|
||||
//}
|
||||
|
||||
private static string EncodeString(string str)
|
||||
{
|
||||
byte[] bStr = Encoding.GetEncoding("koi8r").GetBytes(str);
|
||||
|
||||
Reference in New Issue
Block a user