169 lines
3.7 KiB
C#
169 lines
3.7 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Management.Automation;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using NLog;
|
|
|
|
namespace Mirantis.Murano.WindowsAgent
|
|
{
|
|
[DisplayName("Murano Agent")]
|
|
sealed public class Program : WindowsService
|
|
{
|
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
|
private volatile bool stop;
|
|
private Thread thread;
|
|
private RabbitMqClient rabbitMqClient;
|
|
private int delayFactor = 1;
|
|
private string plansDir;
|
|
|
|
static void Main(string[] args)
|
|
{
|
|
Start(new Program(), args);
|
|
}
|
|
|
|
protected override void OnStart(string[] args)
|
|
{
|
|
base.OnStart(args);
|
|
|
|
Log.Info("Version 0.5.4");
|
|
|
|
this.rabbitMqClient = new RabbitMqClient();
|
|
|
|
var basePath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
|
|
this.plansDir = Path.Combine(basePath, "plans");
|
|
|
|
|
|
if (!Directory.Exists(plansDir))
|
|
{
|
|
Directory.CreateDirectory(plansDir);
|
|
}
|
|
|
|
this.thread = new Thread(Loop);
|
|
this.thread.Start();
|
|
}
|
|
|
|
void Loop()
|
|
{
|
|
const string unknownName = "unknown";
|
|
while (!stop)
|
|
{
|
|
try
|
|
{
|
|
foreach (var file in Directory.GetFiles(this.plansDir, "*.json.result")
|
|
.Where(file => !File.Exists(Path.Combine(this.plansDir, Path.GetFileNameWithoutExtension(file)))))
|
|
{
|
|
var id = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)) ?? unknownName;
|
|
if (id.Equals(unknownName, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
id = "";
|
|
}
|
|
|
|
var result = File.ReadAllText(file);
|
|
Log.Info("Sending results for {0}", id ?? unknownName);
|
|
rabbitMqClient.SendResult(new MqMessage { Body = result, Id = id });
|
|
File.Delete(file);
|
|
}
|
|
|
|
var path = Directory.EnumerateFiles(this.plansDir, "*.json").FirstOrDefault();
|
|
if (path == null)
|
|
{
|
|
var message = rabbitMqClient.GetMessage();
|
|
var id = message.Id;
|
|
if(string.IsNullOrEmpty(id))
|
|
{
|
|
id = unknownName;
|
|
}
|
|
|
|
path = Path.Combine(this.plansDir, string.Format("{0}.json", id));
|
|
File.WriteAllText(path, message.Body);
|
|
Log.Info("Received new execution plan {0}", id);
|
|
message.Ack();
|
|
}
|
|
else
|
|
{
|
|
var id = Path.GetFileNameWithoutExtension(path);
|
|
Log.Info("Executing exising plan {0}", id);
|
|
}
|
|
var executor = new PlanExecutor(path);
|
|
executor.Execute();
|
|
File.Delete(path);
|
|
delayFactor = 1;
|
|
|
|
if (stop) break;
|
|
if (executor.RebootNeeded)
|
|
{
|
|
Reboot();
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
WaitOnException(exception);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void Reboot()
|
|
{
|
|
Log.Info("Going for reboot!!");
|
|
LogManager.Flush();
|
|
/*try
|
|
{
|
|
System.Diagnostics.Process.Start("shutdown.exe", "-r -t 0");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.ErrorException("Cannot execute shutdown.exe", ex);
|
|
}*/
|
|
|
|
|
|
try
|
|
{
|
|
PowerShell.Create().AddCommand("Restart-Computer").AddParameter("Force").Invoke();
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
|
|
Log.FatalException("Reboot exception", exception);
|
|
}
|
|
finally
|
|
{
|
|
Log.Info("Waiting for reboot");
|
|
for (var i = 0; i < 10 * 60 * 5 && !stop; i++)
|
|
{
|
|
Thread.Sleep(100);
|
|
}
|
|
Log.Info("Done waiting for reboot");
|
|
}
|
|
|
|
}
|
|
|
|
private void WaitOnException(Exception exception)
|
|
{
|
|
if (stop) return;
|
|
Log.WarnException("Exception in main loop", exception);
|
|
var i = 0;
|
|
while (!stop && i < 10 * (delayFactor * delayFactor))
|
|
{
|
|
Thread.Sleep(100);
|
|
i++;
|
|
}
|
|
delayFactor = Math.Min(delayFactor + 1, 6);
|
|
}
|
|
|
|
protected override void OnStop()
|
|
{
|
|
stop = true;
|
|
this.rabbitMqClient.Dispose();
|
|
base.OnStop();
|
|
}
|
|
|
|
}
|
|
}
|