This commit is contained in:
Thomas Peterson 2024-12-13 21:12:09 +01:00
parent caca6bb715
commit 39f3516b2e
9 changed files with 381 additions and 185 deletions

View File

@ -12,17 +12,12 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="95257dc5-08bd-4c50-8726-85956b3c2c92" name="Changes" comment=""> <list default="true" id="95257dc5-08bd-4c50-8726-85956b3c2c92" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Nextcloud/Nextcloud.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Nextcloud/Nextcloud.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/HetznerServer/Models/Server.cs" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Models/Server.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Nextcloud/ViewModels/NotesViewModel.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Nextcloud/ViewModels/NotesViewModel.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/HetznerServer/Service/ServerService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Service/ServerService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PSCHelpdesk.sln.DotSettings.user" beforeDir="false" afterPath="$PROJECT_DIR$/PSCHelpdesk.sln.DotSettings.user" afterDir="false" /> <change beforePath="$PROJECT_DIR$/HetznerServer/ViewModels/ServerViewModel.cs" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/ViewModels/ServerViewModel.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj" afterDir="false" /> <change beforePath="$PROJECT_DIR$/HetznerServer/Views/ServerView.axaml" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Views/ServerView.axaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs" beforeDir="false" afterPath="$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Shared/Setting/SettingsManager.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Shared/Setting/SettingsManager.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Shared/Shared.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/Shared/Shared.csproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.deps.json" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.deps.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.dll" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.dll" afterDir="false" /> <change beforePath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.dll" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.dll" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.pdb" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.pdb" afterDir="false" /> <change beforePath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.pdb" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.pdb" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.deps.json" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.deps.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.dll" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.dll" afterDir="false" /> <change beforePath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.dll" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.dll" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.pdb" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.pdb" afterDir="false" /> <change beforePath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.pdb" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/nextcloud/Nextcloud.pdb" afterDir="false" />
</list> </list>
@ -269,7 +264,8 @@
<workItem from="1732868564507" duration="5973000" /> <workItem from="1732868564507" duration="5973000" />
<workItem from="1733129681879" duration="2029000" /> <workItem from="1733129681879" duration="2029000" />
<workItem from="1733213310388" duration="18514000" /> <workItem from="1733213310388" duration="18514000" />
<workItem from="1733247430633" duration="9839000" /> <workItem from="1733247430633" duration="19286000" />
<workItem from="1733729071487" duration="13363000" />
</task> </task>
<task id="LOCAL-00001" summary="Backup"> <task id="LOCAL-00001" summary="Backup">
<option name="closed" value="true" /> <option name="closed" value="true" />
@ -311,7 +307,15 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1733247327690</updated> <updated>1733247327690</updated>
</task> </task>
<option name="localTasksCounter" value="6" /> <task id="LOCAL-00006" summary="Backup">
<option name="closed" value="true" />
<created>1733341591476</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1733341591476</updated>
</task>
<option name="localTasksCounter" value="7" />
<servers /> <servers />
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
@ -440,6 +444,7 @@
</breakpoint-manager> </breakpoint-manager>
<pin-to-top-manager> <pin-to-top-manager>
<pinned-members> <pinned-members>
<PinnedItemInfo parentTag="Type#System.Collections.Generic.KeyValuePair`2" memberName="Value" />
<PinnedItemInfo parentTag="Type#FastBill.Api.Response.SearchCustomer" memberName="Response" /> <PinnedItemInfo parentTag="Type#FastBill.Api.Response.SearchCustomer" memberName="Response" />
</pinned-members> </pinned-members>
</pin-to-top-manager> </pin-to-top-manager>

View File

@ -12,7 +12,37 @@ namespace PSCHelpdesk.Plugins.HetznerServer.Models;
public class Server : ReactiveObject 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; } public string Name { get; set; }
private Instance _instance; private Instance _instance;

View File

@ -35,7 +35,7 @@ public class ServerService: IServerService
{ {
this.reloadServerStatus(); this.reloadServerStatus();
}; };
_reloadTimer.Interval = TimeSpan.FromMinutes(10); _reloadTimer.Interval = TimeSpan.FromMinutes(60);
_reloadTimer.Start(); _reloadTimer.Start();
reloadServer(); reloadServer();
@ -78,6 +78,98 @@ public class ServerService: IServerService
foreach (Server serv in SourceCache.Items) foreach (Server serv in SourceCache.Items)
{ {
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) if (settings.ServerSettings.Count(e => e.ServerId == serv.ServerId) > 0)
{ {
serv.FastBillId = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillId; serv.FastBillId = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillId;
@ -98,11 +190,15 @@ public class ServerService: IServerService
{ {
serv.HasBackup = true; serv.HasBackup = true;
JArray borgMatic = JArray.Parse(command.Result); JArray borgMatic = JArray.Parse(command.Result);
await uiDispatcher.InvokeAsync(() =>
{
serv.BackupLastModified = DateTime.Parse(borgMatic[0]["repository"]["last_modified"].ToString()); 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"); command = client.RunCommand("docker inspect psc_mongodb_1");
if (command.ExitStatus == 0) if (command.ExitStatus == 0)
@ -144,6 +240,12 @@ public class ServerService: IServerService
if (command.ExitStatus == 0) if (command.ExitStatus == 0)
{ {
JArray web = JArray.Parse(command.Result); 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"]; var webEnvArray = web[0]["Config"]["Env"];
foreach (String entry in webEnvArray) foreach (String entry in webEnvArray)
@ -235,8 +337,11 @@ public class ServerService: IServerService
} }
if (serv.PscApiKey.Length > 0)
{
serv.IsGoodIcon = MaterialIconKind.Check; serv.IsGoodIcon = MaterialIconKind.Check;
serv.IsGoodColor = Brushes.Green; serv.IsGoodColor = Brushes.Green;
}
client.Disconnect(); client.Disconnect();
} }
@ -245,29 +350,5 @@ public class ServerService: IServerService
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
} }
}
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);
} }
} }

View File

@ -42,6 +42,10 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase
public ReactiveCommand<SelectionChangedEventArgs, Unit> SelectionChanged { get; } public ReactiveCommand<SelectionChangedEventArgs, Unit> SelectionChanged { get; }
public ReactiveCommand<Unit, Unit> SaveServerSettings { get; } public ReactiveCommand<Unit, Unit> SaveServerSettings { get; }
public ReactiveCommand<Unit, Unit> AptUpdate { get; }
public ReactiveCommand<Unit, Unit> ReScan { get; }
public ReactiveCommand<Unit, Unit> Reboot { get; }
protected readonly ReadOnlyObservableCollection<Server> _server; protected readonly ReadOnlyObservableCollection<Server> _server;
public ReadOnlyObservableCollection<Server> Server => _server; public ReadOnlyObservableCollection<Server> Server => _server;
@ -53,6 +57,9 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase
SelectedServer = new Server(1,"","","","",""); SelectedServer = new Server(1,"","","","","");
SelectionChanged = ReactiveCommand.Create<SelectionChangedEventArgs>(selectionChanged); SelectionChanged = ReactiveCommand.Create<SelectionChangedEventArgs>(selectionChanged);
SaveServerSettings = ReactiveCommand.Create(saveServerSettings); SaveServerSettings = ReactiveCommand.Create(saveServerSettings);
AptUpdate = ReactiveCommand.Create(doAptUpdate);
ReScan = ReactiveCommand.Create(doReScan);
Reboot = ReactiveCommand.Create(doReboot);
_settingsManager = (SettingsManager)Ioc.Default.GetService<ISettingsManager>(); _settingsManager = (SettingsManager)Ioc.Default.GetService<ISettingsManager>();
ServerService.SourceCache.Connect() ServerService.SourceCache.Connect()
// Sort Ascending on the OrderIndex property // Sort Ascending on the OrderIndex property
@ -137,4 +144,37 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase
{ {
ServerService.SaveSettings(SelectedServer); 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);
}
}
}
} }

View File

@ -23,10 +23,17 @@
<TextBlock Margin="0 5" >Suchtext</TextBlock> <TextBlock Margin="0 5" >Suchtext</TextBlock>
<TextBox Text="{Binding SearchText}"></TextBox> <TextBox Text="{Binding SearchText}"></TextBox>
</StackPanel> </StackPanel>
<TextBox Grid.Row="1" Text="{Binding Json}"></TextBox> <StackPanel Orientation="Horizontal" Grid.Row="1" Margin="0 0 0 5">
<Button Content="ReScan" Command="{Binding ReScan}"></Button>
<Button Content="Apt Upgrade" Command="{Binding AptUpdate}"></Button>
<Button Content="Reboot" Command="{Binding Reboot}"></Button>
<!-- <TextBox Grid.Row="1" Text="{Binding Json}"></TextBox>-->
</StackPanel>
<DataGrid Grid.Row="2" ItemsSource="{Binding Server}" <DataGrid Grid.Row="2" ItemsSource="{Binding Server}"
AutoGenerateColumns="False" IsReadOnly="True" AutoGenerateColumns="False" IsReadOnly="True"
GridLinesVisibility="All" GridLinesVisibility="All" CanUserReorderColumns="True"
CanUserResizeColumns="True"
BorderThickness="1" BorderBrush="Gray" BorderThickness="1" BorderBrush="Gray"
x:Name="ServerTable"> x:Name="ServerTable">
<DataGrid.Styles> <DataGrid.Styles>
@ -43,6 +50,13 @@
</EventTriggerBehavior> </EventTriggerBehavior>
</Interaction.Behaviors> </Interaction.Behaviors>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTemplateColumn Header="Select Server">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="30" IsReadOnly="True"> <DataGridTemplateColumn Width="30" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
@ -50,11 +64,37 @@
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Header="Has Restart">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding IsRestartAlways}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Has Need Restart">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding HasNeedRestart}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="75" Header="Id" Binding="{Binding ServerId}"/> <DataGridTextColumn Width="75" Header="Id" Binding="{Binding ServerId}"/>
<DataGridTextColumn Width="*" Header="Name" Binding="{Binding Name}" /> <DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox HorizontalAlignment="Left" Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="60" Header="Status" Binding="{Binding Status}" CellStyleClasses="status" /> <DataGridTextColumn Width="60" Header="Status" Binding="{Binding Status}" CellStyleClasses="status" />
<DataGridTextColumn Width="45" Header="Type" Binding="{Binding Type}" /> <DataGridTextColumn Width="45" Header="Type" Binding="{Binding Type}" />
<DataGridTextColumn Width="*" IsReadOnly="False" Header="IpV4" Binding="{Binding Ipv4}" /> <DataGridTemplateColumn Header="IpV4">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox HorizontalAlignment="Left" Text="{Binding Ipv4}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="*" Header="IpV6" Binding="{Binding Ipv6}" /> <DataGridTextColumn Width="*" Header="IpV6" Binding="{Binding Ipv6}" />
<DataGridTextColumn Header="Datum" <DataGridTextColumn Header="Datum"
Binding="{Binding Datum}" Binding="{Binding Datum}"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.