public async Task <IActionResult> Create() { try { MemoryStream stream = new MemoryStream(); await HttpContext.Request.Body.CopyToAsync(stream); stream.Position = 0; StreamReader reader = new StreamReader(stream); string profilejson = reader.ReadToEnd(); Profile profile = _profileJsonHelper.DeserializeObject(profilejson); var connection = _connectionFinder.GetPrimaryLITEConnection(profile); var manager = _connectionManagerFactory.GetManager(connection) as ILiteConnectionManager; await manager.RegisterLITE(profile); return(CreatedAtRoute("GetLITE", new { username = _connectionFinder.GetPrimaryLifeImageConnection(profile).username }, profile)); //return CreatedAtRoute("GetFile", new { boxUuid = paths[0], fileID = paths[0] }, paths); } catch (TaskCanceledException) { _logger.LogInformation($"Task was canceled."); return(StatusCode(503)); } catch (Exception e) { _logger.LogCritical($"{e.Message} {e.StackTrace}"); return(StatusCode(503)); } }
public ActionResult <List <string> > GetAll() { List <string> list = new List <string>(); foreach (var profile in LiteConnectionManager.LITERegistry) { var connection = _connectionFinder.GetPrimaryLifeImageConnection(profile); list.Add(connection.username); } return(list); }
public async Task RegisterLITE(Profile lite) { try { //server side method the LITE will call to register itself, invoked from LITEController var registered = LITERegistry.ToList().FindAll(e => _connectionFinder.GetPrimaryLifeImageConnection(e).tenantID == _connectionFinder.GetPrimaryLifeImageConnection(lite).tenantID); switch (registered.Count) { case 0: LITERegistry.Add(lite); break; case 1: //already registered, just update registered[0] = lite; break; default: //duplicate entries? break; } await Task.Yield(); } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e); } return; }
private async Task SyncWithCloud(Profile profile) { var cloudConn = _connectionFinder.GetPrimaryLifeImageConnection(profile); if (profile.startupParams.putServerProfile && !cloudConn.loginNeeded) { await _cloudProfileWriter.PutConfigurationToCloud(profile, cloudConn); // During write set modified date to now so it doesn't go back around and reload Profile.modifiedDate = DateTime.Now; } }
public async Task Process() { var taskInfo = $""; var profile = _profileStorage.Current; _logger.Log(LogLevel.Information, "Life Image Transfer Exchange Loop"); try { try { lock (ProfileLocker) { _profileManager.LoadProfile(profile, profile.startupParams.localProfilePath); //Profile.LoadProfile(profile, profile.startupParams.localProfilePath); if (profile.duplicatesDetectionUpload) { string message = "Duplicates detection and elimination process is active for upload process."; _logger.Log(LogLevel.Information, $"{message}"); } else { string message = "Duplicates detection and elimination process is not active for upload process."; _logger.Log(LogLevel.Information, $"{message}"); } if (profile.duplicatesDetectionDownload) { string message = "Duplicates detection and elimination process is active for download process."; _logger.Log(LogLevel.Information, $"{message}"); } else { string message = "Duplicates detection and elimination process is not active for download process."; _logger.Log(LogLevel.Information, $"{message}"); } //var primaryConnection = profile.GetPrimaryLifeImageConnection(); var primaryConnection = _connectionFinder.GetPrimaryLifeImageConnection(profile); if (primaryConnection == null) { throw new Exception($"Primary Connection Missing out of {profile.connections.Capacity} total connections."); } if (platform.Equals("win") && string.IsNullOrEmpty(profile.dcmtkLibPath)) { Console.WriteLine(profile.name); profile.dcmtkLibPath = "tools" + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dcmtk-3.6.3-win64-dynamic"; //profile.SaveProfile(); _profileWriter.SaveProfile(profile).Wait(); } if (!primaryConnection.loginNeeded) { _cloudProfileLoaderService.LoadProfile(profile, primaryConnection).Wait(); //profile.LoadProfile(primaryConnection).Wait(); } //profile.SaveProfile(); _profileWriter.SaveProfile(profile).Wait(); bool isEnabled = false; AppContext.TryGetSwitch("System.Net.Http.useSocketsHttpHandler", out isEnabled); if (isEnabled != profile.useSocketsHttpHandler) { _logger.Log(LogLevel.Debug, $"{taskInfo} Calling AppContext.SetSwitch(\"System.Net.Http.useSocketsHttpHandler\", {profile.useSocketsHttpHandler})"); AppContext.SetSwitch("System.Net.Http.useSocketsHttpHandler", profile.useSocketsHttpHandler); } } } catch (Exception e) { if (e.Message.Contains("Replacement Strategy Needs Full LITE.init()")) { _logger.Log(LogLevel.Critical, $"{taskInfo} Configuration changed received."); } else { _logger.LogFullException(e, $"{taskInfo} Profile Operations Problem: {e.Message}"); } throw e; } //adjust loglevel if necessary // _logger.LogLevel = profile.logger.logLevel; Logger.logger.ConsoleTraceLevel = profile.logger.ConsoleTraceLevel; Logger.logger.FileTraceLevel = profile.logger.FileTraceLevel; Logger.logger.SplunkTraceLevel = profile.logger.SplunkTraceLevel; Logger.logger.TracePattern = profile.logger.TracePattern; //compile the scripts as needed foreach (var myscript in profile.rules.scripts) { if (myscript.script == null) { _logger.Log(LogLevel.Debug, $"compiling {myscript.name}"); _scriptService.Compile(myscript); } } //let's queue up some work _logger.Log(LogLevel.Information, "Life Image Transfer Exchange kickoff start"); var newTaskID = _taskManager.NewTaskID(); await kickOff(newTaskID); _logger.Log(LogLevel.Information, "Life Image Transfer Exchange kickoff end"); if (profile.backlogDetection) { foreach (var conn in profile.connections) { if (conn.toRules.Count > 0) { profile.backlog = true; } } if (profile.backlog) { _logger.Log(LogLevel.Debug, $"{taskInfo} Detected Backlog, skipping kickoffInterval"); await Task.Delay(profile.backlogInterval, _taskManager.cts.Token); profile.backlog = false; } else { await Task.Delay(profile.KickOffInterval, _taskManager.cts.Token); } } else { await Task.Delay(profile.KickOffInterval, _taskManager.cts.Token); } RecoveryCount = 0; } catch (Exception e) { if (LITETask._shutdown) { throw new Exception("Application is terminated"); } ; if (e.Message.Contains("Replacement Strategy Needs Full LITE.init()")) { } else { _logger.Log(LogLevel.Critical, $"{taskInfo} Life Image Transfer Exchange Loop Exception: breaking out of run loop due to unrecoverable exception. {e.Message}"); if (e.InnerException != null) { _logger.Log(LogLevel.Critical, $"Inner Exception: {e.InnerException}"); } } } }
public void InitConnections(Profile profile, List <string> argsList, object ProfileLocker) { Throw.IfNull(profile); try { //if (profile.startupParams.generateSchema == true) //{ // Directory.CreateDirectory("JSONSchema"); // Logger.logger.Log(TraceEventType.Information, "Registering Newtonsoft.Json.Schema.License."); // Newtonsoft.Json.Schema.License.RegisterLicense( // "3606-tXIhm+ANdVeBkIPZuD16/AYNS41W5oqeEbwG065ms41NYxGKi2qqOtqI9rjSh4TTaOAnj9dYS0hk6cFHAoKcuFJZXg9dhTaBzx/Hx7Oq43qE7bJyWPyHaTaGRMZlZEq2xiPMzOl9x4gBNkgdLz3sJaG9thZJRLSwCdcp0qXXxZ17IklkIjozNjA2LCJFeHBpcnlEYXRlIjoiMjAxOS0wMy0xNVQyMDoyNDozMS43MzkzNzU0WiIsIlR5cGUiOiJKc29uU2NoZW1hQnVzaW5lc3MifQ=="); // Logger.logger.Log(TraceEventType.Information, // "Newtonsoft.Json.Schema.License registration complete."); // var types = Assembly // .GetExecutingAssembly() // .GetTypes(); // //.Where(t => t.Namespace.StartsWith("LifeImageLite")); // foreach (var file in Directory.EnumerateFiles("JSONSchema")) // { // File.Delete(file); // } // foreach (var type in types) // { // if (type.IsPublic && type.Namespace == "LifeImageLite" && type.Name == "Profile") // { // string schemaString = null; // try // { // JSchemaGenerator generator = new JSchemaGenerator(); // JSchema schema = generator.Generate(type); // schemaString = schema.ToString(); // if (Logger.logger.FileTraceLevel == "Verbose") // Logger.logger.Log(TraceEventType.Verbose, $"JSON Schema for {type}"); // if (Logger.logger.FileTraceLevel == "Verbose") // Logger.logger.Log(TraceEventType.Verbose, $"{schemaString}"); // if (schemaString != null && !type.Name.Contains("<")) // { // File.WriteAllTextAsync( // "JSONSchema" + Path.DirectorySeparatorChar + type.Name + ".schema.json", // schemaString); // } // } // catch (Newtonsoft.Json.Schema.JSchemaException e) // { // Logger.logger.Log(TraceEventType.Warning, $"{e.Message} {e.StackTrace}"); // } // } // } //} } catch (NullReferenceException) { _logger.Log(LogLevel.Information, $"no startupProfile.startupParams.generateSchema."); } Directory.CreateDirectory(profile.tempPath); //Load Profile from file if specified var arg = argsList.Find(x => x.Contains("loadProfileFile=")); if (arg != null) { var fileName = argsList.Find(x => x.Contains("loadProfileFile=")).Substring(16); if (fileName != null) { _logger.Log(LogLevel.Information, $"loadProfileFile={fileName}. Loading this profile"); lock (ProfileLocker) { profile.startupParams.localProfilePath = fileName; profile.startupParams.saveProfilePath = fileName; //Profile.LoadProfile(profile, profile.startupParams.localProfilePath); //Profile.LoadProfile(profile, profile.startupParams.localProfilePath); _profileManager.LoadProfile(profile, profile.startupParams.localProfilePath); } } } else { _logger.Log(LogLevel.Information, $"no loadProfileFile arg. Using startup.config.json"); _logger.Log(LogLevel.Information, $"profile.startupParams.localProfilePath: {profile.startupParams.localProfilePath}"); if (profile.startupParams.localProfilePath != null) { lock (ProfileLocker) { _profileManager.LoadProfile(profile, profile.startupParams.localProfilePath); //Profile.LoadProfile(profile, profile.startupParams.localProfilePath); } } else { //Find the current profile from the LITE.sh file var currentProfile = File.ReadAllText("LITE.sh"); var elements = currentProfile.Split(" "); currentProfile = elements[2].Substring(16); lock (ProfileLocker) { profile.startupParams.localProfilePath = currentProfile; profile.startupParams.saveProfilePath = currentProfile; profile.startupParams.getServerProfile = true; profile.startupParams.putServerProfile = true; profile.startupParams.generateSchema = true; profile.startupParams.validateProfile = true; //Profile.LoadProfile(profile, currentProfile); _profileManager.LoadProfile(profile, currentProfile); } } } _logger.Log(LogLevel.Debug, $"Replacing Logger.logger with Profile.logger"); // Logger.logger.logLevel = profile.logger.logLevel; Logger.logger.ConsoleTraceLevel = profile.logger.ConsoleTraceLevel; Logger.logger.FileTraceLevel = profile.logger.FileTraceLevel; Logger.logger.SplunkTraceLevel = profile.logger.SplunkTraceLevel; Logger.logger.TracePattern = profile.logger.TracePattern; //initialize the connections var primary = _connectionFinder.GetPrimaryLifeImageConnection(profile); //LifeImageCloudConnection primary = profile.GetPrimaryLifeImageConnection(); /* AMG Why do we need to find primary connection if we are not using it? What is there is more than 1. The code is expecting only one primary connection */ Rules rules = profile.rules; foreach (var conn in profile.connections) { if (conn.enabled == true) { var connManager = _connectionManagerFactory.GetManager(conn); connManager.Init(); //conn.init(); } } //Create the specified folders Directory.CreateDirectory(profile.tempPath); }
/// <summary> /// Merges another profile into this one in an additive fashion unless version is higher /// This should preserve the arg > file > remote precedence with the exception of variables required to be defined /// at program startup like kickoffInterval, logRetentionDays, name, etc. /// Command line args boot with version = 0 unless otherwise specified. /// To add settings without agent restart, add at Cloud or agent with same version. /// To replace settings without agent restart, add at Cloud or agent with incremented version.Note: live queues will reset. /// If you switch profiles at the agent, the name will (should) be different and merge is skipped. /// </summary> /// <param name="current"></param> /// <param name="profile"></param> public void MergeProfile(Profile current, Profile profile) { Throw.IfNull(current); bool bootstrap = current.name.Equals("Bootstrap"); if (profile == null) { return; } lock (current) { //game over!! Someone switched profiles on the client or server or it's not time if ((!current.name.Equals(profile.name) && !bootstrap) || !(DateTime.Now > profile.activationTime)) { _logger.Log(LogLevel.Debug, $"inbound profile name: {profile.name} this name: {current.name} bootstrap: {bootstrap}, inbound activationTime: {profile.activationTime} using ignore strategy"); return; } if (profile.version > current.version) { _logger.Log(LogLevel.Debug, $"inbound profile version {profile.version} greater than current version {current.version}, using replacement strategy"); // foreach (var conn in this.connections) // { // Logger.logger.Log(TraceEventType.Information, $"stopping {conn.name}"); // conn.stop(); // } _taskManager.Stop(); //replace all settings, realizing this dumps all live queues and connections //may want code that is more fine grained and doesn't drop work in progress. current.activationTime = profile.activationTime; current.availableCodeVersions = profile.availableCodeVersions; //this.backlog; shb nonserialized current.backlogDetection = profile.backlogDetection; current.backlogInterval = profile.backlogInterval; /* 2020-05-22 AMG added properties to profile */ current.duplicatesDetectionUpload = profile.duplicatesDetectionUpload; current.duplicatesDetectionDownload = profile.duplicatesDetectionDownload; current.duplicatesDetectionInterval = profile.duplicatesDetectionInterval; current.modalityList = profile.modalityList; current.modalityDetectionArchivePeriod = profile.modalityDetectionArchivePeriod; current.connections = profile.connections; current.dcmtkLibPath = profile.dcmtkLibPath; //this.errors = profile.errors; shb not needed //this.highWait = profile.highWait; shb nonserialized current.highWaitDelay = profile.highWaitDelay; //this.jsonInError = profile.jsonInError; shb not needed //this.jsonSchemaPath = profile.jsonSchemaPath; shb not needed current.KickOffInterval = profile.KickOffInterval; //this.lastKickOff = profile.lastKickOff; shb not needed //this.lastStartup = profile.lastStartup; shb not needed current.Labels = profile.Labels; //2018-02-13 shb need to assign inbound profile.logger settings during replacement strategy var primary = _connectionFinder.GetPrimaryLifeImageConnection(current); //current.logger = new Logger("default"); current.logger = new Logger(); current.logger.ConsoleTraceLevel = profile.logger.ConsoleTraceLevel; current.logger.SplunkTraceLevel = profile.logger.SplunkTraceLevel; current.logger.FileTraceLevel = profile.logger.FileTraceLevel; current.logger.TracePattern = profile.logger.TracePattern; Logger.logger = current.logger; //Logger.logger.Init(); _loggerManager.Init(current.logger); current.LogFileSize = profile.LogFileSize; current.logRetentionDays = profile.logRetentionDays; current.maxTaskDuration = profile.maxTaskDuration; //this.mediumWait = profile.mediumWait; shb nonserialized current.mediumWaitDelay = profile.mediumWaitDelay; current.minFreeDiskBytes = profile.minFreeDiskBytes; //this.modifiedDate = profile.modifiedDate; shb not needed current.name = profile.name; Profile._overrideVersionAndModifiedDate = Profile._overrideVersionAndModifiedDate; //profileConverter not needed current.recoveryInterval = profile.recoveryInterval; //this.rowVersion = profile.rowVersion; shb not merged because we get this from the api call current.rules = profile.rules; current.run = profile.run; //this.runningCodeVersion = profile.runningCodeVersion; shb not needed // Only allow startup params in startup profile this.startupParams = profile.startupParams; //startupConfigFilePath shb not needed //this.startupParams = profile.startupParams; shb not needed current.taskDelay = profile.taskDelay; current.tempFileRetentionHours = profile.tempFileRetentionHours; current.tempPath = profile.tempPath; current.updateCodeVersion = profile.updateCodeVersion; current.updateUrl = profile.updateUrl; current.updatePassword = profile.updatePassword; current.updateUsername = profile.updateUsername; current.useSocketsHttpHandler = profile.useSocketsHttpHandler; current.version = profile.version; // shb will change the value of tempPath and write back to a profile if saved (including possibly the same profile). //convenience assignment to reduce number of calls to get Windows ProgramData folder. current.tempPath = _util.GetTempFolder(current.tempPath); _profileWriter.SaveProfile(current).Wait(); if (!bootstrap) { throw new Exception("Replacement Strategy Needs Full LITE.init(), throwing this exception on purpose!"); } } else if (profile.version == current.version) { _logger.Log(LogLevel.Debug, $"inbound profile version {profile.version} same as current version {current.version}, using merge strategy"); //2018-03-03 shb need to assign inbound profile.logger settings during merge so we can have non-destructive loglevel changes // this.logger.logLevel = profile.logger.logLevel; var primary = _connectionFinder.GetPrimaryLifeImageConnection(current); //current.logger = new Logger("default"); current.logger = new Logger(); // this.logger.logLevel = profile.logger.logLevel; current.logger.ConsoleTraceLevel = profile.logger.ConsoleTraceLevel; current.logger.SplunkTraceLevel = profile.logger.SplunkTraceLevel; current.logger.FileTraceLevel = profile.logger.FileTraceLevel; current.logger.TracePattern = profile.logger.TracePattern; Logger.logger = current.logger; //Logger.logger.Init(); _loggerManager.Init(current.logger); if (current.updateCodeVersion == null) { current.updateCodeVersion = profile.updateCodeVersion; } //merge settings in additive fashion except override ones that startup with predefined values foreach (var srcConn in profile.connections) { Connection destConn = current.connections.Find(e => e.name == srcConn.name); if (destConn == null) { //srcConn.profile = this; current.connections.Add(srcConn); } } //dev hack to load in script example. Script script = new Script { name = "Hello World", source = "using System.Diagnostics; if (logger.logLevel == \"Trace\") logger.Log(TraceEventType.Verbose, $\"Hello World\");" }; if (current.rules.scripts.Find(e => e.name == script.name) == null) { _logger.Log(LogLevel.Debug, $"adding script {script.name}"); current.rules.scripts.Add(script); } foreach (var rule in profile.rules.destRules) { if (!current.rules.destRules.Exists(e => e.name == rule.name)) { current.rules.destRules.Add(rule); } } var msg = ""; foreach (var rule in current.rules.destRules) { msg += rule.name + " "; } _logger.Log(LogLevel.Debug, $"{current.rules.destRules.Count} rules after merge: {msg}"); } else if (profile.version < current.version) { //ignore _logger.Log(LogLevel.Debug, $"inbound profile version {profile.version} less than current version {current.version}, using ignore strategy"); return; } else { //ignore _logger.Log(LogLevel.Debug, $"Unexpected condition inbound version {profile.version} current version {current.version}, using ignore strategy"); return; } } }