mirror of
https://bitbucket.org/anguist/ntpa
synced 2026-09-26 10:54:04 +00:00
366 lines
14 KiB
C#
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 (PeerSummaryPageConfiguration PeerSummaryPage in server.PeerSummaryPages)
|
|
scheduler.Add (new PeerSummaryJob (server.Menu, PeerSummaryPage, 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;
|
|
}
|
|
}
|
|
} |