Files
ntpa/Ntp.Analyzer.Process/Initializer.cs
T
2016-04-02 11:18:17 +02:00

366 lines
14 KiB
C#

//
// Initializer.cs
//
// Author:
// Carsten Sonne Larsen <cs@innolan.dk>
//
// Copyright (c) 2013-2016 Carsten Sonne Larsen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;
using Ntp.Analyzer.Config;
using Ntp.Analyzer.Config.Graph;
using Ntp.Analyzer.Config.Page;
using Ntp.Analyzer.Data;
using Ntp.Analyzer.Log;
using Ntp.Config;
using Ntp.Monitor.Server;
using Ntp.Process;
using Ntp.Analyzer.Process.Description;
using Ntp.Analyzer.Config.Root;
using Ntp.Monitor.Client;
using System.Net;
using Ntp.System;
using Ntp.Analyzer.Objects;
using System.Linq;
using Ntp.Analyzer.Objects.Live;
namespace Ntp.Analyzer.Process
{
public sealed class Initializer
{
/// <summary>
/// Initializes a new instance of the <see cref="Ntp.Analyzer.Process.Initializer" /> class.
/// </summary>
/// <param name="configFile">Config file to use.</param>
/// <param name="pid">Process ID. Only used for logging.</param>
/// <param name="name">Name of process ID. Used for shutting down.</param>
public Initializer (string configFile, int pid, string name)
{
this.configFile = configFile;
this.pid = pid;
this.name = name;
nodes = new List<IRequest> ();
listeners = new List<Listener> ();
this.version = VersionInfo.Number;
}
private static bool firstrun = true;
private readonly string version;
private readonly string configFile;
private readonly int pid;
private readonly string name;
private readonly List<IRequest> nodes;
private readonly List<Listener> listeners;
private Configuration config;
private LogBase log;
private Scheduler scheduler;
private bool ready;
public Scheduler Scheduler {
get { return scheduler; }
}
public LogBase Log {
get { return log; }
}
public List<IRequest> Nodes {
get { return nodes; }
}
public List<Listener> Listeners {
get { return listeners; }
}
public bool Ready {
get { return ready; }
}
/// <summary>
/// Run the NTP Analyzer.
/// </summary>
public void Run ()
{
// Neutralize.
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
bool proceed = InitializeConfiguration ();
if (proceed)
proceed = InitializeLog ();
if (proceed) {
InitializeState ();
InitializeDatabase ();
InitializeData ();
InitializeListerners ();
InitializeCluster ();
InitializeScheduler ();
}
ready = proceed;
firstrun = false;
}
/// <summary>
/// Initializes the configuration.
/// </summary>
private bool InitializeConfiguration ()
{
if (!File.Exists (configFile)) {
Console.WriteLine ("Cannot find configuration file: " + configFile);
return false;
}
// Read config.
try {
string[] configLines = File.ReadAllLines (configFile);
ConfigurationBlock block = new ConfigurationBlock (configLines);
config = Configuration.Create (block);
} catch (Exception ex) {
Console.WriteLine ("Cannot read configuration file: " + configFile);
Console.WriteLine (ex.Message);
return false;
}
if (ConfigurationBase.Errors != String.Empty) {
Console.WriteLine ("Errors in configuration file");
Console.WriteLine (ConfigurationBase.Errors);
return false;
}
return true;
}
/// <summary>
/// Initializes the log.
/// </summary>
private bool InitializeLog ()
{
// Create log.
try {
log = LogFactory.CreateLog (config.Log);
log.Initialize ();
} catch (Exception ex) {
Console.WriteLine ("Cannot create log file. " + ex.Message);
return false;
}
// Initialize log.
if (firstrun)
log.WriteLine ("NTP Analyzer " + version + " started.", Severity.Notice);
log.WriteLine ("Using configuration " + configFile, Severity.Notice);
log.WriteLine ("Running with pid " + pid, Severity.Notice);
log.WriteLine ("Instance named " + name, Severity.Notice);
return true;
}
/// <summary>
/// Initializes the application and database state.
/// </summary>
private void InitializeState ()
{
// Initialize application state
ApplicationState.Version = version;
ApplicationState.Pid = pid;
ApplicationState.Name = name;
ApplicationState.Config = config;
ApplicationState.ConfigFile = configFile;
ApplicationState.Log = log;
}
private void InitializeDatabase()
{
// Initialize database connection
DataConnection.DatabaseName = config.Database.Name;
DataConnection.String = config.Database.ConnectionString;
DataConnection.InitializeString = config.Database.InitializeConnectionString;
DataConnection.Initialize = config.Database.Initialize;
DataConnection.Log = log;
DataFace.Reset ();
// Initialize database tables
if (config.Database.Initialize) {
try {
DataInitializer initializer = new DataInitializer (log);
initializer.CreateDatabase ();
} catch (Exception e) {
log.WriteLine ("Error during initialization of database.", Severity.Error);
log.WriteLine (e.Message, Severity.Debug);
log.WriteLine (e, Severity.Trace);
}
}
}
private void InitializeData()
{
if (!config.Database.Initialize)
return;
try {
// Initialize hosts
foreach (ServerConfiguration server in config.Servers) {
Host host = DataFace.Instance.Hosts.SingleOrDefault (h => h.Id == server.HostId);
if (host == null) {
IPAddress ip;
try {
ip = Dns.GetHostAddresses (server.ServerName) [0];
} catch {
ip = IPAddress.None;
}
host = new Host (server.HostId, server.ServerName, ip.ToString (), null);
DataFace.Instance.Hosts.Save (host);
Log.WriteLine (String.Format (
"Created a new host in database ID {0} with name {1} and IP {2}.",
server.HostId, server.ServerName, ip),
Severity.Info);
}
// Initialize peers
foreach (AssociationEntry entry in DataFace.Instance.NtpqCache[server.ServerName]) {
IEnumerable<Peer> peerList = DataFace.Instance.Peers.Where (p => p.Ip == entry.Remote);
if (peerList.Count () == 0) {
Peer peer = new Peer (entry.Remote, entry.Remote, null);
DataFace.Instance.Peers.Save (peer);
Log.WriteLine (String.Format (
"Created a new peer in database with name {0} and IP {1}.",
entry.Remote, entry.Remote),
Severity.Info);
}
}
}
} catch (Exception e) {
log.WriteLine ("Could not populate tables with data.", Severity.Error);
log.WriteLine (e.Message, Severity.Debug);
log.WriteLine (e, Severity.Trace);
}
}
/// <summary>
/// Initializes the listerners.
/// </summary>
private void InitializeListerners ()
{
try {
foreach (ListenerConfiguration monitor in config.Monitors) {
Listener listener = new Listener (monitor.Ip, monitor.Port, log);
listener.Open ();
listeners.Add (listener);
log.WriteLine ("Listening " + listener, Severity.Notice);
}
} catch (Exception e) {
log.WriteLine ("Error during initialization of listerners.", Severity.Error);
log.WriteLine (e.Message, Severity.Debug);
log.WriteLine (e, Severity.Trace);
}
}
/// <summary>
/// Initializes the cluster nodes.
/// </summary>
private void InitializeCluster ()
{
if (config.Cluster == null)
return;
try {
foreach (NodeConfiguration node in config.Cluster.Nodes) {
IPAddress ip = IPAddress.Parse (node.Ip);
IRequest req = new TextRequest (ip, node.Port);
nodes.Add (req);
log.WriteLine ("Reqesting to cluster " + node.Address, Severity.Notice);
}
} catch (Exception e) {
log.WriteLine ("Error during initialization of cluster node.", Severity.Error);
log.WriteLine (e.Message, Severity.Debug);
log.WriteLine (e, Severity.Trace);
}
}
/// <summary>
/// Initializes the scheduler.
/// </summary>
private void InitializeScheduler ()
{
Job.Reset ();
try {
scheduler = new Scheduler (log);
log.WriteLine ("Initializing jobs.", Severity.Debug);
scheduler.Add (new BulkStatJob (config.Bulk, scheduler.Log));
// Add jobs to schedule.
foreach (ServerConfiguration server in config.Servers) {
scheduler.Add (new HostStatJob (server.HostStats, scheduler.Log));
scheduler.Add (new HostIOStatJob (server.HostIoStats, scheduler.Log));
scheduler.Add (new PeerStatJob (server.PeerStats, scheduler.Log));
scheduler.Add (new AboutPageJob (server.Menu, server.AboutPage, scheduler.Log));
foreach (PeerPageConfiguration peerPage in server.PeerPages)
scheduler.Add (new PeerPageJob (server.Menu, peerPage, scheduler.Log));
foreach (HostPageConfiguration hostPage in server.HostPages)
scheduler.Add (new HostPageJob (server.Menu, hostPage, scheduler.Log));
foreach (HostGraphConfiguration hostGraph in server.HostGraphs)
scheduler.Add (new HostGraphJob (hostGraph, scheduler.Log));
foreach (TrafficGraphConfiguration trafficGraph in server.TrafficGraphs)
scheduler.Add (new TrafficGraphJob (trafficGraph, scheduler.Log));
foreach (PeerGraphConfiguration peerGraph in server.PeerGraphs)
scheduler.Add (new PeerGraphJob (peerGraph, scheduler.Log));
foreach (PeerSummeryPageConfiguration peerSummeryPage in server.PeerSummeryPages)
scheduler.Add (new PeerSummeryJob (server.Menu, peerSummeryPage, scheduler.Log));
scheduler.Add (new HostGraphPageJob (server.HostGraphPage, scheduler.Log));
scheduler.Add (new PeerGraphPageJob (server.PeerGraphPage, scheduler.Log));
}
// Add the survaliance/notify job.
if (config.Notify != null) {
NotifyJob adminJob = new NotifyJob (config.Notify, log, pid, configFile);
scheduler.Add (adminJob);
adminJob.SetJobList (scheduler);
// Done
log.WriteLine ("All jobs initialized.", Severity.Debug);
}
} catch (Exception e) {
log.WriteLine ("Error during initialization of scheduler.", Severity.Error);
log.WriteLine (e.Message, Severity.Debug);
log.WriteLine (e, Severity.Trace);
}
ApplicationState.Scheduler = scheduler;
ApplicationState.StartupTime = scheduler.StartTime;
}
}
}