pschelpdesk/HetznerServer/Service/ServerService.cs
2024-12-25 11:15:24 +01:00

357 lines
14 KiB
C#

using System.Collections.ObjectModel;
using System.Net.Http.Headers;
using Avalonia.Media;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.DependencyInjection;
using DynamicData;
using DynamicData.Binding;
using HetznerCloudApi;
using Material.Icons;
using Newtonsoft.Json.Linq;
using PSCHelpdesk.Plugins.HetznerServer.Models;
using PSCHelpdesk.Shared.Service;
using PSCHelpdesk.Shared.Setting;
using PSCHelpdesk.Shared.Tasks;
using ReactiveUI;
using Renci.SshNet;
namespace PSCHelpdesk.Plugins.HetznerServer.Service;
public class ServerService: IServerService
{
public SourceCache<Server, long> SourceCache = new (x => x.ServerId);
private SettingsManager _settingsManager;
private readonly DispatcherTimer _reloadTimer = new DispatcherTimer();
private string _searchText = string.Empty;
private ITaskManager _taskManager;
private readonly IToastManager? _toastManager;
public ServerService()
{
_settingsManager = (SettingsManager)Ioc.Default.GetService<ISettingsManager>();
_taskManager = Ioc.Default.GetService<ITaskManager>();
_toastManager = (IToastManager)Ioc.Default.GetService<IToastManager>();
this._reloadTimer.Tick += (sender, args) =>
{
this.reloadServerStatus();
};
_reloadTimer.Interval = TimeSpan.FromMinutes(60);
_reloadTimer.Start();
reloadServer();
}
private async Task reloadServer()
{
var settings = new Settings();
_settingsManager.LoadPluginSettings("HetznerSettings", settings);
if (settings.HetznerApiKey != "")
{
HetznerCloudClient hetznerCloudClient = new HetznerCloudClient(settings.HetznerApiKey);
List<HetznerCloudApi.Object.Server.Server> list = await hetznerCloudClient.Server.Get();
foreach (var server in list)
{
var uiDispatcher = Ioc.Default.GetService<IUserInterfaceDispatchService>();
await uiDispatcher.InvokeAsync(() =>
{
SourceCache.AddOrUpdate(new Server(server.Id, server.Name, server.ServerType.Name, server.Status,
server.PublicNet.Ipv4.Ip, server.PublicNet.Ipv6.Ip));
});
}
}
await Task.Run(async () => await this.reloadServerStatus());
}
private async Task reloadServerStatus()
{
var uiDispatcher = Ioc.Default.GetService<IUserInterfaceDispatchService>();
await uiDispatcher.InvokeAsync(() =>
{
_reloadTimer.Stop();
});
var settings = new Settings();
_settingsManager.LoadPluginSettings("HetznerSettings", settings);
foreach (Server serv in SourceCache.Items)
{
if (serv.Status.Equals("running", StringComparison.OrdinalIgnoreCase))
{
doScan(serv);
}
}
await uiDispatcher.InvokeAsync(() =>
{
this._reloadTimer.Start();
});
}
public void SaveSettings(Server selectedServer)
{
var settings = new Settings();
_settingsManager.LoadPluginSettings("HetznerSettings", settings);
if (settings.ServerSettings.Count(e => e.ServerId == selectedServer.ServerId) > 0)
{
settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).FastBillId = selectedServer.FastBillId;
settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).PscApiKey = selectedServer.PscApiKey;
settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).FastBillNr = selectedServer.FastBillNr;
}
else
{
settings.ServerSettings.Add(new ServerSetting(selectedServer.ServerId, selectedServer.PscApiKey, selectedServer.FastBillId, selectedServer.FastBillNr));
}
_settingsManager.SavePluginSettings("HetznerSettings", settings);
}
public void DoAptUpgrade(Server serv)
{
var connectionInfo = new ConnectionInfo(serv.Ipv4,
"root",
new PrivateKeyAuthenticationMethod("root",
new PrivateKeyFile(this._settingsManager.CoreSettings.PrivateSSHKeyPath)));
using (var client = new SshClient(connectionInfo))
{
try
{
client.Connect();
var command = client.RunCommand("apt upgrade -y && apt auto-remove -y");
if (command.ExitStatus == 0)
{
Console.WriteLine(serv.Name + " SUCCESS upgraded apt.");
}
else
{
Console.WriteLine(serv.Name + " ERROR upgraded apt.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public void DoReboot(Server serv)
{
var connectionInfo = new ConnectionInfo(serv.Ipv4,
"root",
new PrivateKeyAuthenticationMethod("root",
new PrivateKeyFile(this._settingsManager.CoreSettings.PrivateSSHKeyPath)));
using (var client = new SshClient(connectionInfo))
{
try
{
client.Connect();
var command = client.RunCommand("reboot");
if (command.ExitStatus == 0)
{
Console.WriteLine(serv.Name + " SUCCESS Reboot");
}
else
{
Console.WriteLine(serv.Name + " ERROR Reboot");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public void DoReScan(Server serv)
{
doScan(serv);
}
async private void doScan(Server serv)
{
var settings = new Settings();
_settingsManager.LoadPluginSettings("HetznerSettings", settings);
if (settings.ServerSettings.Count(e => e.ServerId == serv.ServerId) > 0)
{
serv.FastBillId = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillId;
serv.FastBillNr = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillNr;
serv.PscApiKey = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).PscApiKey;
}
var connectionInfo = new ConnectionInfo(serv.Ipv4,
"root",
new PrivateKeyAuthenticationMethod("root", new PrivateKeyFile(this._settingsManager.CoreSettings.PrivateSSHKeyPath)));
using (var client = new SshClient(connectionInfo))
{
try
{
client.Connect();
var command = client.RunCommand("borgmatic info --json");
if (command.ExitStatus == 0)
{
serv.HasBackup = true;
JArray borgMatic = JArray.Parse(command.Result);
serv.BackupLastModified = DateTime.Parse(borgMatic[0]["repository"]["last_modified"].ToString());
}
command = client.RunCommand("whereis needrestart");
if (command.ExitStatus == 0)
{
if (command.Result.Length > 20)
{
serv.HasNeedRestart = true;
}
}
command = client.RunCommand("docker inspect psc_mongodb_1");
if (command.ExitStatus == 0)
{
JArray mongoDB = JArray.Parse(command.Result);
var mongoDBEnvArray = mongoDB[0]["Config"]["Env"];
foreach (String entry in mongoDBEnvArray)
{
var mongodDBexploded = entry.Split("=");
if (mongodDBexploded[0] == "MONGO_VERSION")
{
serv.MongoVersion = mongodDBexploded[1];
}
}
}
command = client.RunCommand("docker inspect psc_mysql_1");
if (command.ExitStatus == 0)
{
JArray mongoDB = JArray.Parse(command.Result);
var mongoDBEnvArray = mongoDB[0]["Config"]["Env"];
foreach (String entry in mongoDBEnvArray)
{
var mongodDBexploded = entry.Split("=");
if (mongodDBexploded[0] == "MARIADB_VERSION")
{
serv.MysqlVersion = mongodDBexploded[1];
}
}
}
command = client.RunCommand("docker ps|wc -l");
if (command.ExitStatus == 0)
{
serv.RunningContainerCount = int.Parse(command.Result);
}
command = client.RunCommand("docker inspect psc_web_1");
if (command.ExitStatus == 0)
{
JArray web = JArray.Parse(command.Result);
var hostConfigArray = web[0]["HostConfig"];
if (hostConfigArray["RestartPolicy"]["Name"].ToString() == "always")
{
serv.IsRestartAlways = true;
}
var webEnvArray = web[0]["Config"]["Env"];
foreach (String entry in webEnvArray)
{
var webExploded = entry.Split("=");
if (webExploded[0] == "LETSENCRYPT_HOST")
{
var webHosts = webExploded[1].Split(",");
serv.Domains.Clear();
foreach (String dom in webHosts)
{
serv.Domains.Add(new Domain(dom));
}
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/ld+json"));
httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client");
try
{
var stringTask = httpClient.GetStringAsync("https://" + webHosts[0] + "/apps/api/system/version");
var msg = await stringTask;
JObject versionMSg = JObject.Parse(msg);
serv.Datum = versionMSg["datum"].ToString();
serv.Release = float.Parse(versionMSg["release"].ToString());
}
catch (Exception ex)
{
}
}
}
}
if (serv.PscApiKey != "" && serv.Domains.Count > 0)
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/ld+json"));
httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client");
httpClient.DefaultRequestHeaders.Add("apiKey", serv.PscApiKey);
try
{
var stringPlugins =
httpClient.GetStringAsync("https://" + serv.Domains.First().Name + "/apps/api/plugins");
var msg = await stringPlugins;
JObject pluginMsg = JObject.Parse(msg);
foreach (var plugin in pluginMsg["data"])
{
serv.Plugins.Add(new Plugin()
{
Installed = bool.Parse(plugin["installed"].ToString()),
Title = plugin["title"].ToString(),
Uuid = plugin["uuid"].ToString()
});
}
}
catch (Exception ex)
{
}
}
if (serv.PscApiKey != "" && serv.Domains.Count > 0)
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/ld+json"));
httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client");
httpClient.DefaultRequestHeaders.Add("apiKey", serv.PscApiKey);
try
{
var stringPlugins =
httpClient.GetStringAsync("https://" + serv.Domains.First().Name + "/apps/api/system/info");
var msg = await stringPlugins;
JObject systemInfo = JObject.Parse(msg);
serv.Instance.SftpUserName = systemInfo["sftpUserName"].ToString();
serv.Instance.SftpPassword = systemInfo["sftpPassword"].ToString();
serv.Instance.SftpHostName = systemInfo["sftpHost"].ToString();
serv.Instance.SmtpOwn = bool.Parse(systemInfo["smtpOwn"].ToString());
}
catch (Exception ex)
{
}
}
if (serv.PscApiKey.Length > 0)
{
serv.IsGoodIcon = MaterialIconKind.Check;
serv.IsGoodColor = Brushes.Green;
}
client.Disconnect();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}