Ejemplo n.º 1
0
    private static AsyncPolicy CreateRetryPolicy(IConfiguration configuration, Extensions.Logging.ILogger logger)
    {
        var retryMigrations = false;

        bool.TryParse(configuration["RetryMigrations"], out retryMigrations);

        // Only use a retry policy if configured to do so.
        // When running in an orchestrator/K8s, it will take care of restarting failed services.
        if (retryMigrations)
        {
            return(Policy.Handle <Exception>().
                   WaitAndRetryForeverAsync(
                       sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
                       onRetry: (exception, retry, timeSpan) =>
            {
                logger.LogWarning(
                    exception,
                    "Exception {ExceptionType} with message {Message} detected during database migration (retry attempt {retry})",
                    exception.GetType().Name,
                    exception.Message,
                    retry);
            }
                       ));
        }

        return(Policy.NoOpAsync());
    }
Ejemplo n.º 2
0
        public static async Task <int> MainAsync(IConfiguration configuration)
        {
            // Bring up the logger before anything else so we can log errors ASAP
            ILogger logger = SetupLogger(configuration);

            logger.LogInformation("Starting module management agent.");

            VersionInfo versionInfo = VersionInfo.Get(VersionInfoFileName);

            if (versionInfo != VersionInfo.Empty)
            {
                logger.LogInformation($"Version - {versionInfo.ToString(true)}");
            }
            LogLogo(logger);

            string mode;

            string   configSourceConfig;
            string   backupConfigFilePath;
            int      maxRestartCount;
            TimeSpan intensiveCareTime;
            int      coolOffTimeUnitInSeconds;
            bool     usePersistentStorage;
            string   storagePath;
            string   edgeDeviceHostName;
            string   dockerLoggingDriver;
            Dictionary <string, string> dockerLoggingOptions;
            IEnumerable <AuthConfig>    dockerAuthConfig;
            int configRefreshFrequencySecs;

            try
            {
                mode = configuration.GetValue(Constants.ModeKey, "docker");
                configSourceConfig       = configuration.GetValue <string>("ConfigSource");
                backupConfigFilePath     = configuration.GetValue <string>("BackupConfigFilePath");
                maxRestartCount          = configuration.GetValue <int>("MaxRestartCount");
                intensiveCareTime        = TimeSpan.FromMinutes(configuration.GetValue <int>("IntensiveCareTimeInMinutes"));
                coolOffTimeUnitInSeconds = configuration.GetValue("CoolOffTimeUnitInSeconds", 10);
                usePersistentStorage     = configuration.GetValue("UsePersistentStorage", true);
                storagePath                = GetStoragePath(configuration);
                edgeDeviceHostName         = configuration.GetValue <string>(Constants.EdgeDeviceHostNameKey);
                dockerLoggingDriver        = configuration.GetValue <string>("DockerLoggingDriver");
                dockerLoggingOptions       = configuration.GetSection("DockerLoggingOptions").Get <Dictionary <string, string> >() ?? new Dictionary <string, string>();
                dockerAuthConfig           = configuration.GetSection("DockerRegistryAuth").Get <List <AuthConfig> >() ?? new List <AuthConfig>();
                configRefreshFrequencySecs = configuration.GetValue("ConfigRefreshFrequencySecs", 3600);
            }
            catch (Exception ex)
            {
                logger.LogCritical(AgentEventIds.Agent, ex, "Fatal error reading the Agent's configuration.");
                return(1);
            }

            IContainer container;

            try
            {
                var builder = new ContainerBuilder();
                builder.RegisterModule(new LoggingModule(dockerLoggingDriver, dockerLoggingOptions));
                Option <string>           productInfo      = versionInfo != VersionInfo.Empty ? Option.Some(versionInfo.ToString()) : Option.None <string>();
                Option <UpstreamProtocol> upstreamProtocol = configuration.GetValue <string>(Constants.UpstreamProtocolKey).ToUpstreamProtocol();
                switch (mode.ToLowerInvariant())
                {
                case Constants.DockerMode:
                    var    dockerUri = new Uri(configuration.GetValue <string>("DockerUri"));
                    string deviceConnectionString = configuration.GetValue <string>("DeviceConnectionString");
                    builder.RegisterModule(new AgentModule(maxRestartCount, intensiveCareTime, coolOffTimeUnitInSeconds, usePersistentStorage, storagePath));
                    builder.RegisterModule(new DockerModule(deviceConnectionString, edgeDeviceHostName, dockerUri, dockerAuthConfig, upstreamProtocol, productInfo));
                    break;

                case Constants.IotedgedMode:
                    string managementUri      = configuration.GetValue <string>(Constants.EdgeletManagementUriVariableName);
                    string workloadUri        = configuration.GetValue <string>(Constants.EdgeletWorkloadUriVariableName);
                    string iothubHostname     = configuration.GetValue <string>(Constants.IotHubHostnameVariableName);
                    string deviceId           = configuration.GetValue <string>(Constants.DeviceIdVariableName);
                    string moduleId           = configuration.GetValue(Constants.ModuleIdVariableName, Constants.EdgeAgentModuleIdentityName);
                    string moduleGenerationId = configuration.GetValue <string>(Constants.EdgeletModuleGenerationIdVariableName);
                    builder.RegisterModule(new AgentModule(maxRestartCount, intensiveCareTime, coolOffTimeUnitInSeconds, usePersistentStorage, storagePath, Option.Some(new Uri(workloadUri)), moduleId, Option.Some(moduleGenerationId)));
                    builder.RegisterModule(new EdgeletModule(iothubHostname, edgeDeviceHostName, deviceId, new Uri(managementUri), new Uri(workloadUri), dockerAuthConfig, upstreamProtocol, productInfo));
                    break;

                default:
                    throw new InvalidOperationException($"Mode '{mode}' not supported.");
                }

                switch (configSourceConfig.ToLowerInvariant())
                {
                case "twin":
                    builder.RegisterModule(new TwinConfigSourceModule(backupConfigFilePath, configuration, versionInfo, TimeSpan.FromSeconds(configRefreshFrequencySecs)));
                    break;

                case "local":
                    builder.RegisterModule(new FileConfigSourceModule("config.json", configuration));
                    break;

                default:
                    throw new InvalidOperationException($"ConfigSource '{configSourceConfig}' not supported.");
                }

                container = builder.Build();
            }
            catch (Exception ex)
            {
                logger.LogCritical(AgentEventIds.Agent, ex, "Fatal error building application.");
                return(1);
            }

            (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler)
                = ShutdownHandler.Init(ShutdownWaitPeriod, logger);

            int returnCode;

            using (IConfigSource unused = await container.Resolve <Task <IConfigSource> >())
            {
                Option <Agent> agentOption = Option.None <Agent>();

                try
                {
                    Agent agent = await container.Resolve <Task <Agent> >();

                    agentOption = Option.Some(agent);
                    while (!cts.Token.IsCancellationRequested)
                    {
                        try
                        {
                            await agent.ReconcileAsync(cts.Token);
                        }
                        catch (Exception ex) when(!ex.IsFatal())
                        {
                            logger.LogWarning(AgentEventIds.Agent, ex, "Agent reconcile concluded with errors.");
                        }
                        await Task.Delay(TimeSpan.FromSeconds(5), cts.Token);
                    }
                    logger.LogInformation("Closing module management agent.");

                    returnCode = 0;
                }
                catch (OperationCanceledException)
                {
                    logger.LogInformation("Main thread terminated");
                    returnCode = 0;
                }
                catch (Exception ex)
                {
                    logger.LogCritical(AgentEventIds.Agent, ex, "Fatal error starting Agent.");
                    returnCode = 1;
                }

                // Attempt to report shutdown of Agent
                await Cleanup(agentOption, logger);

                completed.Set();
            }
            handler.ForEach(h => GC.KeepAlive(h));
            return(returnCode);
        }
Ejemplo n.º 3
0
 public void LogWarning(string message) => _logger.LogWarning(message);