diff --git a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml index f895e55..f7dda8e 100644 --- a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml +++ b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml @@ -12,17 +12,12 @@ - - - - - - - - + + + + - @@ -269,7 +264,8 @@ - + + - @@ -440,6 +444,7 @@ + diff --git a/HetznerServer/Models/Server.cs b/HetznerServer/Models/Server.cs index a90276a..659edd8 100644 --- a/HetznerServer/Models/Server.cs +++ b/HetznerServer/Models/Server.cs @@ -12,7 +12,37 @@ namespace PSCHelpdesk.Plugins.HetznerServer.Models; public class Server : ReactiveObject { - public long ServerId { get; set; } + private bool _isChecked; + + public bool IsChecked + { + get => _isChecked; + set => this.RaiseAndSetIfChanged(ref _isChecked, value); + } + + private bool _hasNeedRestart; + + public bool HasNeedRestart + { + get => _hasNeedRestart; + set => this.RaiseAndSetIfChanged(ref _hasNeedRestart, value); + } + + private bool _isRestartAlways; + + public bool IsRestartAlways + { + get => _isRestartAlways; + set => this.RaiseAndSetIfChanged(ref _isRestartAlways, value); + } + + private long _serverId; + + public long ServerId + { + get => _serverId; + set => this.RaiseAndSetIfChanged(ref _serverId, value); + } public string Name { get; set; } private Instance _instance; diff --git a/HetznerServer/Service/ServerService.cs b/HetznerServer/Service/ServerService.cs index c4407fc..fd36bd8 100644 --- a/HetznerServer/Service/ServerService.cs +++ b/HetznerServer/Service/ServerService.cs @@ -35,7 +35,7 @@ public class ServerService: IServerService { this.reloadServerStatus(); }; - _reloadTimer.Interval = TimeSpan.FromMinutes(10); + _reloadTimer.Interval = TimeSpan.FromMinutes(60); _reloadTimer.Start(); reloadServer(); @@ -78,174 +78,7 @@ public class ServerService: IServerService foreach (Server serv in SourceCache.Items) { - 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); - await uiDispatcher.InvokeAsync(() => - { - serv.BackupLastModified = DateTime.Parse(borgMatic[0]["repository"]["last_modified"].ToString()); - }); - - } - 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 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) - { - } - - } - - serv.IsGoodIcon = MaterialIconKind.Check; - serv.IsGoodColor = Brushes.Green; - - client.Disconnect(); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - + doScan(serv); } await uiDispatcher.InvokeAsync(() => @@ -270,4 +103,252 @@ public class ServerService: IServerService } _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); + } + } + } } \ No newline at end of file diff --git a/HetznerServer/ViewModels/ServerViewModel.cs b/HetznerServer/ViewModels/ServerViewModel.cs index 286c3d0..695887f 100644 --- a/HetznerServer/ViewModels/ServerViewModel.cs +++ b/HetznerServer/ViewModels/ServerViewModel.cs @@ -42,6 +42,10 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase public ReactiveCommand SelectionChanged { get; } public ReactiveCommand SaveServerSettings { get; } + public ReactiveCommand AptUpdate { get; } + public ReactiveCommand ReScan { get; } + public ReactiveCommand Reboot { get; } + protected readonly ReadOnlyObservableCollection _server; public ReadOnlyObservableCollection Server => _server; @@ -53,6 +57,9 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase SelectedServer = new Server(1,"","","","",""); SelectionChanged = ReactiveCommand.Create(selectionChanged); SaveServerSettings = ReactiveCommand.Create(saveServerSettings); + AptUpdate = ReactiveCommand.Create(doAptUpdate); + ReScan = ReactiveCommand.Create(doReScan); + Reboot = ReactiveCommand.Create(doReboot); _settingsManager = (SettingsManager)Ioc.Default.GetService(); ServerService.SourceCache.Connect() // Sort Ascending on the OrderIndex property @@ -137,4 +144,37 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase { ServerService.SaveSettings(SelectedServer); } + + void doAptUpdate() + { + foreach (var serv in Server) + { + if (serv.IsChecked) + { + ServerService.DoAptUpgrade(serv); + } + } + } + + void doReboot() + { + foreach (var serv in Server) + { + if (serv.IsChecked) + { + ServerService.DoReboot(serv); + } + } + } + + void doReScan() + { + foreach (var serv in Server) + { + if (serv.IsChecked) + { + ServerService.DoReScan(serv); + } + } + } } \ No newline at end of file diff --git a/HetznerServer/Views/ServerView.axaml b/HetznerServer/Views/ServerView.axaml index bb63366..f6774aa 100644 --- a/HetznerServer/Views/ServerView.axaml +++ b/HetznerServer/Views/ServerView.axaml @@ -23,10 +23,17 @@ Suchtext - + + + + + + + @@ -43,6 +50,13 @@ + + + + + + + @@ -50,11 +64,37 @@ + + + + + + + + + + + + + + - + + + + + + + - + + + + + + +