Модели Apps, Scheduler

This commit is contained in:
Mikhail Kuznetsov
2023-06-13 13:57:55 +10:00
parent 8a72550ff0
commit b22c401156
12 changed files with 360 additions and 60 deletions

View File

@@ -14,10 +14,7 @@ namespace PARR.AIHIT.MappingProfiles
.ForMember(d => d.LinkEK, o => o.MapFrom(s => s.Attributes!["СВЯЗАННЫЙ_ЭК"]!.Value.Trim()))
.ForMember(d => d.Status, o => o.MapFrom(s => s.Attributes!["СТАТУС"]!.Value.Trim()))
.ForMember(d => d.WorkGroup, o => o.MapFrom(s => (s.Attributes!["РАБОЧАЯ_ГР_ОТВ_ЗАК"] != null) ? s.Attributes!["РАБОЧАЯ_ГР_ОТВ_ЗАК"]!.Value.Trim() : ""))
.ForMember(d => d.Responsible, o => o.MapFrom(s => s.Attributes!["ОТВЕТСТВЕННЫЙ_ЗАК"]!.Value.Trim()))
.ForMember(d => d.OS, o => o.MapFrom(s => (s.Attributes!["ОС"] != null) ? s.Attributes!["ОС"]!.Value.Trim() : ""))
.ForMember(d => d.DB, o => o.MapFrom(s => (s.Attributes!["СУБД"] != null) ? s.Attributes!["СУБД"]!.Value.Trim() : ""))
.ForMember(d => d.APP, o => o.MapFrom(s => (s.Attributes!["СП"] != null) ? s.Attributes!["СП"]!.Value.Trim() : ""));
.ForMember(d => d.Responsible, o => o.MapFrom(s => s.Attributes!["ОТВЕТСТВЕННЫЙ_ЗАК"]!.Value.Trim()));
//CreateMap<PARR.DAL.Models.Host, PARR.DAL.Models.Host>()
// .ForMember(d => d.HostName, o => o.MapFrom(s => s.HostName))

View File

@@ -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; ;
//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;
//}
if (isChanged && !await hostService.CommitAsync())
logger.LogError($"Не удалось обновить узел {mappedHost.IP} {mappedHost.RegionalEK}");
else logger.LogInformation($"Обновлён узел {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} -----");
}
}
else
{
if (!await hostService.CreateAsync(mappedHost) || !await hostService.CommitAsync())
logger.LogError($"Не удалось создать узел {mappedHost.IP} {mappedHost.RegionalEK}");
// Синхронизация 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);

View File

@@ -14,5 +14,10 @@ namespace PARR.DAL.Context
public DbSet<Host> Hosts { get; set; }
public DbSet<Job> Jobs { get; set; }
public DbSet<JobJournal> JobJournals { get; set; }
public DbSet<Application> Applications { get; set; }
public DbSet<ApplicationType> ApplicationTypes { get; set; }
public DbSet<ApplicationInHost> ApplicationsInHosts { get; set; }
public DbSet<Scheduler> Schedulers { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
namespace PARR.DAL.Contracts
{
public enum ApplicationTypesEnum
{
APP,
OS,
DB
}
}

View File

@@ -0,0 +1,29 @@
using PARR.DAL.Models.Base;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PARR.DAL.Models
{
[Table("Applications")]
public class Application : IBase
{
[Key]
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset? DateModified { get; set; }
public required string Name { get; set; }
public Guid ApplicationTypeId { get; set; }
[ForeignKey(nameof(ApplicationTypeId))]
public ApplicationType? ApplicationType { get; set; }
public ICollection<ApplicationInHost> ApplicationsInHosts { get; set; } = new HashSet<ApplicationInHost>();
}
}
}

View File

@@ -0,0 +1,28 @@
using PARR.DAL.Models.Base;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PARR.DAL.Models
{
[Table("ApplicationsinHosts")]
public class ApplicationInHost : IBase
{
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset? DateModified { get; set; }
public Guid ApplicationId { get; set; }
[ForeignKey(nameof(ApplicationId))]
public Application? Application { get; set; }
public Guid HostId { get; set; }
[ForeignKey(nameof(HostId))]
public Host? Host { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using PARR.DAL.Models.Base;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PARR.DAL.Models
{
[Table("ApplicationTypes")]
public class ApplicationType : IBase
{
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset? DateModified { get; set; }
public required string Name { get; set; }
public string? Description { get; set; }
}
}

View File

@@ -11,19 +11,17 @@ namespace PARR.DAL.Models
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset? DateModified { get; set; }
public string HostName { get; set; }
public string HostName { get; set; }
public required string IP { get; set; }
public string? RegionalEK { get; set; }
public string? LinkEK { get; set; }
public string? Status { get; set; }
public string? WorkGroup { get; set; }
public string? Responsible { get; set; }
public string? OS { get; set; }
public string? DB { get; set; }
public string? APP { get; set; }
public ICollection<JobJournal> JobJournals { get; set; } = new HashSet<JobJournal>();
public ICollection<ApplicationInHost> ApplicationsInHosts { get; set; } = new HashSet<ApplicationInHost>();
}
}

View File

@@ -0,0 +1,19 @@
using PARR.DAL.Models.Base;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PARR.DAL.Models
{
[Table("Schedulers")]
public class Scheduler : IBase
{
[Key]
public Guid Id { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset? DateModified { get; set; }
public string? Name { get; set; }
public int Frequency { get; set; }
public required DateTimeOffset StartAt { get; set; }
public bool IsEnabled { get; set; }
}
}

View File

@@ -21,7 +21,7 @@ namespace PARR.DAL.Services.Implementations
this.logger = logger;
}
public async Task<Host?> GetHostByIPAndRegionalEKAsync(string IP, string RegionalEK)
public async Task<Host?> GetHostWithAppsAsync(string IP, string RegionalEK)//TODO
{
try
{

View File

@@ -1,4 +1,3 @@
using Microsoft.Extensions.Configuration;
using PARR.AIHIT;
using PARR.DAL;
using PARR.Mail;
@@ -12,10 +11,8 @@ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;
var workerSettings = new WorkerSettings();
workerSettings = hostContext.Configuration.GetSection(nameof(WorkerSettings)).Get<WorkerSettings>();
hostContext.Configuration.GetSection(nameof(WorkerSettings)).Bind(workerSettings);
services.AddSingleton(workerSettings);