Initialer Import der Synology Scripts

This commit is contained in:
root
2026-08-05 08:43:57 +02:00
commit 5e32a7c411
404 changed files with 79932 additions and 0 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
$Config = @{
Cluster = "INFRA"
CSVGroups = "C:\\Shutdown\\Input.csv"
LogPath = "C:\\Shutdown"
VCenterServer = $null
StorageSystem = $null
```
CredFiles = @{
vCenter = "C:\Shutdown\vcenter-cred.xml"
storage = "C:\Shutdown\storage.xml"
}
Tools = @{
Plink = "C:\Program Files (x86)\PuTTY\plink.exe"
}
```
}
+44
View File
@@ -0,0 +1,44 @@
# Config laden
. "C:\\Shutdown\\Config.ps1"
# Module laden
Import-Module ".\\Modules\\Logging.psm1"
Import-Module ".\\Modules\\Credentials.psm1"
Import-Module ".\\Modules\\VCenter.psm1"
Import-Module ".\\Modules\\Shutdown.psm1"
# Logging
$LogFile = New-LogFile $Config.LogPath
Start-Transcript -Path $LogFile -Append
Write-Host "[INFO] Shutdown gestartet"
# Credentials
$vCenterCred = Get-CredentialFromFile $Config.CredFiles.vCenter
$storageCred = Get-CredentialFromFile $[Config.CredFiles.storage](http://Config.CredFiles.storage)
# vCenter Verbindung
Connect-ToVCenter -Server $Config.VCenterServer -Credential $vCenterCred
# CSV laden
$VMGroups = Import-Csv $Config.CSVGroups -Delimiter ";"
$VMGroups | ForEach-Object { $*.Gruppe = [int]$*.Gruppe }
$VMGroups = $VMGroups | Sort-Object Gruppe
# Shutdown Pipeline
Stop-UnknownVMs -VMGroups $VMGroups -ExcludeRegex "vCLS|vSAN"
Stop-VMsByGroup -VMGroups $VMGroups
Stop-VMHostSafe -VMHost "GWHost01"
Stop-ClusterSafe -Cluster $Config.Cluster -Reason "Automated Shutdown"
Stop-Transcript
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
function Get-CredentialFromFile {
param([string]$Path)
```
if (!(Test-Path $Path)) {
throw "Credential file not found: $Path"
}
return Import-Clixml -Path $Path
```
}
+25
View File
@@ -0,0 +1,25 @@
function New-LogFile {
param($LogPath)
```
if (!(Test-Path $LogPath)) {
New-Item -ItemType Directory -Path $LogPath | Out-Null
}
return Join-Path $LogPath ("Shutdown_{0}.log" -f (Get-Date -Format "yyyy-MM-dd_HH-mm-ss"))
```
}
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
```
$line = "[{0}] {1}" -f $Level, $Message
Write-Host $line
```
}
+63
View File
@@ -0,0 +1,63 @@
function Stop-VMsByGroup {
param($VMGroups)
```
$groups = $VMGroups.Gruppe | Select-Object -Unique
foreach ($g in $groups) {
$names = ($VMGroups | Where-Object Gruppe -eq $g).Server
$vms = Get-VM | Where-Object { $names -contains $_.Name }
foreach ($vm in $vms) {
if ($vm.PowerState -eq "PoweredOn") {
Shutdown-VMGuest -VM $vm -Confirm:$false -ErrorAction SilentlyContinue
}
}
Start-Sleep -Seconds 60
}
```
}
function Stop-UnknownVMs {
param($VMGroups, $ExcludeRegex)
```
$vms = Get-VM | Where-Object {
($VMGroups.Server -notcontains $_.Name) -and
($_.Name -notmatch $ExcludeRegex)
}
foreach ($vm in $vms) {
if ($vm.PowerState -eq "PoweredOn") {
Shutdown-VMGuest -VM $vm -Confirm:$false -ErrorAction SilentlyContinue
}
}
```
}
function Stop-ClusterSafe {
param(
[string]$Cluster,
[string]$Reason
)
```
Stop-VsanCluster -Cluster $Cluster -PowerOffReason $Reason -ErrorAction Stop | Out-Null
```
}
function Stop-VMHostSafe {
param([string]$VMHost)
```
Set-VMHost -VMHost $VMHost -State Maintenance -Confirm:$false | Out-Null
Stop-VMHost -VMHost $VMHost -Confirm:$false -ErrorAction Stop | Out-Null
```
}
+15
View File
@@ -0,0 +1,15 @@
function Connect-ToVCenter {
param(
[string]$Server,
[pscredential]$Credential
)
```
Import-Module VMware.PowerCLI -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Connect-VIServer -Server $Server -Credential $Credential -ErrorAction Stop | Out-Null
```
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
$Config = @{
Cluster = "INFRA"
CSVGroups = "C:\\Shutdown\\Input.csv"
LogPath = "C:\\Shutdown"
```
VCenterServer = "vcsa01.local"
CredFiles = @{
vCenter = "C:\Shutdown\vcenter-cred.xml"
storage = "C:\Shutdown\storage.xml"
}
```
}
+27
View File
@@ -0,0 +1,27 @@
. "C:\\Shutdown\\Config.ps1"
Import-Module ".\\Modules\\Logging.psm1"
Import-Module ".\\Modules\\Retry.psm1"
Import-Module ".\\Modules\\Credentials.psm1"
Import-Module ".\\Modules\\VCenter.psm1"
Import-Module ".\\Modules\\Shutdown.psm1"
Start-Transcript -Path (Join-Path $Config.LogPath "shutdown.log")
Write-Log "Shutdown started"
$vCenterCred = Get-CredentialFromFile $Config.CredFiles.vCenter
Connect-ToVCenter -Server $Config.VCenterServer -Credential $vCenterCred
$VMGroups = Import-Csv $Config.CSVGroups -Delimiter ";"
$VMGroups | ForEach-Object { $*.Gruppe = [int]$*.Gruppe }
Stop-UnknownVMs -VMGroups $VMGroups -ExcludeRegex "vCLS|vSAN"
Stop-VMsByGroup -VMGroups $VMGroups
Stop-ClusterSafe -Cluster $Config.Cluster -Reason "Automated shutdown"
Write-Log "Shutdown completed"
Stop-Transcript
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
function Get-CredentialFromFile {
param([string]$Path)
```
if (!(Test-Path $Path)) {
throw "Missing credential file: $Path"
}
Import-Clixml -Path $Path
```
}
+26
View File
@@ -0,0 +1,26 @@
enum LogLevel {
INFO
WARN
ERROR
DEBUG
}
function Write-Log {
param(
[string]$Message,
[LogLevel]$Level = [LogLevel]::INFO
)
```
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$line = "[$ts][$Level] $Message"
switch ($Level) {
"INFO" { Write-Host $line -ForegroundColor Gray }
"WARN" { Write-Host $line -ForegroundColor Yellow }
"ERROR" { Write-Host $line -ForegroundColor Red }
"DEBUG" { Write-Host $line -ForegroundColor DarkGray }
}
```
}
+24
View File
@@ -0,0 +1,24 @@
function Invoke-Retry {
param(
[scriptblock]$Action,
[int]$Retries = 3,
[int]$DelaySeconds = 5,
[string]$Name = "Operation"
)
```
for ($i = 1; $i -le $Retries; $i++) {
try {
return & $Action
}
catch {
Write-Log "$Name failed ($i/$Retries): $($_.Exception.Message)" -Level WARN
if ($i -eq $Retries) { throw }
Start-Sleep $DelaySeconds
}
}
```
}
+68
View File
@@ -0,0 +1,68 @@
function Stop-VMParallel {
param([array]$VMs, [int]$Throttle = 8)
```
$VMs | ForEach-Object -Parallel {
Import-Module VMware.PowerCLI -ErrorAction SilentlyContinue
$vm = $_
if ($vm.PowerState -ne "PoweredOn") { return }
try {
Shutdown-VMGuest -VM $vm -Confirm:$false -ErrorAction Stop
}
catch {
Write-Host "[ERROR] VM failed: $($vm.Name)"
}
} -ThrottleLimit $Throttle
```
}
function Stop-VMsByGroup {
param($VMGroups)
```
$groups = $VMGroups.Gruppe | Sort-Object -Unique
foreach ($g in $groups) {
$names = ($VMGroups | Where-Object Gruppe -eq $g).Server
$vms = Get-VM | Where-Object { $names -contains $_.Name }
if ($vms) {
Stop-VMParallel -VMs $vms
Start-Sleep 30
}
}
```
}
function Stop-UnknownVMs {
param($VMGroups, $ExcludeRegex)
```
$vms = Get-VM | Where-Object {
($VMGroups.Server -notcontains $_.Name) -and
($_.Name -notmatch $ExcludeRegex)
}
if ($vms) {
Stop-VMParallel -VMs $vms
}
```
}
function Stop-ClusterSafe {
param([string]$Cluster, [string]$Reason)
```
Invoke-Retry -Name "Cluster shutdown" -Action {
Stop-VsanCluster -Cluster $Cluster -PowerOffReason $Reason -ErrorAction Stop | Out-Null
}
```
}
+16
View File
@@ -0,0 +1,16 @@
function Connect-ToVCenter {
param(
[string]$Server,
[pscredential]$Credential
)
```
Import-Module VMware.PowerCLI -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Invoke-Retry -Name "vCenter connect" -Action {
Connect-VIServer -Server $Server -Credential $Credential -ErrorAction Stop | Out-Null
}
```
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
$Config = @{
Cluster = "INFRA"
CSVGroups = "C:\\Shutdown\\Input.csv"
LogPath = "C:\\Shutdown"
```
VCenterServer = "vcsa01.local"
CredFiles = @{
vCenter = "C:\Shutdown\vcenter-cred.xml"
storage = "C:\Shutdown\storage.xml"
}
```
}
+27
View File
@@ -0,0 +1,27 @@
. "C:\\Shutdown\\Config.ps1"
Import-Module ".\\Modules\\Logging.psm1"
Import-Module ".\\Modules\\Retry.psm1"
Import-Module ".\\Modules\\Credentials.psm1"
Import-Module ".\\Modules\\VCenter.psm1"
Import-Module ".\\Modules\\Shutdown.psm1"
Start-Transcript -Path (Join-Path $Config.LogPath "shutdown.log")
Write-Log "Shutdown started"
$vCenterCred = Get-CredentialFromFile $Config.CredFiles.vCenter
Connect-ToVCenter -Server $Config.VCenterServer -Credential $vCenterCred
$VMGroups = Import-Csv $Config.CSVGroups -Delimiter ";"
$VMGroups | ForEach-Object { $*.Gruppe = [int]$*.Gruppe }
Stop-UnknownVMs -VMGroups $VMGroups -ExcludeRegex "vCLS|vSAN"
Stop-VMsByGroup -VMGroups $VMGroups
Stop-ClusterSafe -Cluster $Config.Cluster -Reason "Automated shutdown"
Write-Log "Shutdown completed"
Stop-Transcript
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
function Get-CredentialFromFile {
param([string]$Path)
```
if (!(Test-Path $Path)) {
throw "Missing credential file: $Path"
}
Import-Clixml -Path $Path
```
}
+26
View File
@@ -0,0 +1,26 @@
enum LogLevel {
INFO
WARN
ERROR
DEBUG
}
function Write-Log {
param(
[string]$Message,
[LogLevel]$Level = [LogLevel]::INFO
)
```
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$line = "[$ts][$Level] $Message"
switch ($Level) {
"INFO" { Write-Host $line -ForegroundColor Gray }
"WARN" { Write-Host $line -ForegroundColor Yellow }
"ERROR" { Write-Host $line -ForegroundColor Red }
"DEBUG" { Write-Host $line -ForegroundColor DarkGray }
}
```
}
+24
View File
@@ -0,0 +1,24 @@
function Invoke-Retry {
param(
[scriptblock]$Action,
[int]$Retries = 3,
[int]$DelaySeconds = 5,
[string]$Name = "Operation"
)
```
for ($i = 1; $i -le $Retries; $i++) {
try {
return & $Action
}
catch {
Write-Log "$Name failed ($i/$Retries): $($_.Exception.Message)" -Level WARN
if ($i -eq $Retries) { throw }
Start-Sleep $DelaySeconds
}
}
```
}
+68
View File
@@ -0,0 +1,68 @@
function Stop-VMParallel {
param([array]$VMs, [int]$Throttle = 8)
```
$VMs | ForEach-Object -Parallel {
Import-Module VMware.PowerCLI -ErrorAction SilentlyContinue
$vm = $_
if ($vm.PowerState -ne "PoweredOn") { return }
try {
Shutdown-VMGuest -VM $vm -Confirm:$false -ErrorAction Stop
}
catch {
Write-Host "[ERROR] VM failed: $($vm.Name)"
}
} -ThrottleLimit $Throttle
```
}
function Stop-VMsByGroup {
param($VMGroups)
```
$groups = $VMGroups.Gruppe | Sort-Object -Unique
foreach ($g in $groups) {
$names = ($VMGroups | Where-Object Gruppe -eq $g).Server
$vms = Get-VM | Where-Object { $names -contains $_.Name }
if ($vms) {
Stop-VMParallel -VMs $vms
Start-Sleep 30
}
}
```
}
function Stop-UnknownVMs {
param($VMGroups, $ExcludeRegex)
```
$vms = Get-VM | Where-Object {
($VMGroups.Server -notcontains $_.Name) -and
($_.Name -notmatch $ExcludeRegex)
}
if ($vms) {
Stop-VMParallel -VMs $vms
}
```
}
function Stop-ClusterSafe {
param([string]$Cluster, [string]$Reason)
```
Invoke-Retry -Name "Cluster shutdown" -Action {
Stop-VsanCluster -Cluster $Cluster -PowerOffReason $Reason -ErrorAction Stop | Out-Null
}
```
}
+16
View File
@@ -0,0 +1,16 @@
function Connect-ToVCenter {
param(
[string]$Server,
[pscredential]$Credential
)
```
Import-Module VMware.PowerCLI -ErrorAction Stop
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Invoke-Retry -Name "vCenter connect" -Action {
Connect-VIServer -Server $Server -Credential $Credential -ErrorAction Stop | Out-Null
}
```
}
View File
View File
View File
+37
View File
@@ -0,0 +1,37 @@
Import-Module VMware.PowerCLI
. .\Config.ps1
Import-Module .\Environment.psm1
Import-Module .\Modules\Logging.psm1
Import-Module .\Modules\Utils.psm1
Import-Module .\Modules\VM.psm1
Import-Module .\Modules\Cluster.psm1
Import-Module .\Modules\Storage.psm1
$global:LogFile = Join-Path $Config.LogPath ("shutdown_{0}.log" -f (Get-Date -Format "yyyyMMdd_HHmmss"))
Start-Transcript -Path $LogFile
$envData = Get-Environment
$vCenterCred = Import-Clixml $Config.Cred.VCenter
$storageCred = Import-Clixml $Config.Cred.Storage
Connect-VIServer $envData.vCenter -Credential $vCenterCred -ErrorAction Stop
$VMGroups = Get-VMGroups $Config.CSVGroups
$AllVMs = Get-VM
Shutdown-VMGroups $VMGroups
$filtered = Get-FilteredVMs -AllVMs $AllVMs -Groups $VMGroups -ExcludeRegex $Config.ExcludeRegex
Stop-VMsParallel -VMs $filtered
Shutdown-GWHost -GWHost $envData.GWHost
Shutdown-Cluster -Cluster $Config.INCluster
# optional:
# Shutdown-Storage -StorageSystem $envData.Storage -Cred $storageCred -Plink $Config.Plink
Stop-Transcript
View File
View File
View File
View File
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+63
View File
@@ -0,0 +1,63 @@
Add-Type -AssemblyName PresentationFramework
[xml]$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Proxmox Manager" Height="350" Width="525">
<Grid>
<Button Name="CheckHostsButton" Content="Check Hosts" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="50" Margin="10"/>
<Button Name="ListServersButton" Content="List Servers" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="50" Margin="120,10,0,0"/>
<Button Name="CreateVMButton" Content="Create VM" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="50" Margin="230,10,0,0"/>
<TextBox Name="OutputTextBox" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,70,0,0" Height="200" Width="480"/>
</Grid>
</Window>
"@
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$Window = [Windows.Markup.XamlReader]::Load($reader)
$CheckHostsButton = $Window.FindName("CheckHostsButton")
$ListServersButton = $Window.FindName("ListServersButton")
$CreateVMButton = $Window.FindName("CreateVMButton")
$OutputTextBox = $Window.FindName("OutputTextBox")
# Verbindung zu Proxmox
$ProxmoxServer = "https://proxmox.example.com:8006/api2/json"
$ProxmoxUser = "root@pam"
$ProxmoxPassword = "yourpassword"
$ProxmoxRealm = "pam"
$null = Connect-PVEModule -Server $ProxmoxServer -User $ProxmoxUser -Password $ProxmoxPassword -Realm $ProxmoxRealm
# Event Handler für CheckHostsButton
$CheckHostsButton.Add_Click({
$OutputTextBox.AppendText("Checking Hosts..." + [Environment]::NewLine)
# Hier können Sie den Status Ihrer Proxmox Hosts überprüfen
})
# Event Handler für ListServersButton
$ListServersButton.Add_Click({
$OutputTextBox.AppendText("Listing Servers..." + [Environment]::NewLine)
# Hier können Sie die Liste der Server anzeigen
})
# Event Handler für CreateVMButton
$CreateVMButton.Add_Click({
$OutputTextBox.AppendText("Creating VM from Excel data..." + [Environment]::NewLine)
# Excel-Datei lesen
$excelPath = "C:\path\to\your\vm_data.xlsx"
$vmData = Import-Excel -Path $excelPath
foreach ($vm in $vmData) {
$name = $vm.Name
$memory = $vm.Memory
$cpu = $vm.CPU
$OutputTextBox.AppendText("Creating VM: $name" + [Environment]::NewLine)
New-PVEVM -Node 'pve' -VMID 100 -Name $name -Memory $memory -Sockets $cpu
}
})
$Window.ShowDialog() | Out-Null
+13119
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -0,0 +1,27 @@
# Benutzername, Gruppe und Passwort eingeben
$username = Read-Host "Geben Sie den Benutzernamen ein"
$group = Read-Host "Geben Sie den Gruppennamen ein"
$password = Read-Host "Geben Sie das Passwort ein" -AsSecureString
# Konvertiere Passwort in Klartext
$passwordPlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
# Liste der Clients
#$clients = @("client1", "client2", "client3", "client4", "client5", "client6", "client7", "client8", "client9", "client10")
$clietns = @("192.168.1.249.")
foreach ($client in $clients) {
# SSH-Verbindung herstellen
$sshSession = New-SSHSession -ComputerName $client -Credential $cred
# Benutzer erstellen
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "sudo useradd -m -s /bin/bash $username"
# Gruppe erstellen und Benutzer hinzufügen
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "sudo groupadd $group"
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "sudo usermod -aG $group $username"
# Passwort setzen
$plaintext = [System.Text.Encoding]::UTF8.GetBytes("$username:$passwordPlainText")
$base64 = [Convert]::ToBase64String($plaintext)
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "echo $base64 | base64 -d | sudo chpasswd"
}
+45
View File
@@ -0,0 +1,45 @@
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,120)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please enter the information in the space below:'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($textBox)
$form.Topmost = $true
$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $textBox.Text
$x
}
+21
View File
@@ -0,0 +1,21 @@
$clients = @("192.168.1.249")
foreach ($client in $clients) {
$sshSession = New-SSHSession -ComputerName $client -Credential $cred
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "sudo useradd -m -s /bin/bash username"
}
$groupName = "neue_gruppe"
foreach ($client in $clients) {
$sshSession = New-SSHSession -ComputerName $client -Credential $cred
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "sudo groupadd $groupName"
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "sudo usermod -aG $groupName username"
}
$password = "Passwort123!"
foreach ($client in $clients) {
$sshSession = New-SSHSession -ComputerName $client -Credential $cred
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "username", $securePassword
Invoke-SSHCommand -SessionId $sshSession.SessionId -Command "echo 'username:$password' | sudo chpasswd"
}
+222
View File
@@ -0,0 +1,222 @@
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[ValidateScript({$_.Host -eq 'download.vulnhub.com'})]
[System.Uri]
$VulnhubURI,
[Parameter(Mandatory = $true)]
[ValidateScript({
if (-not (Test-Path $_)) {
throw "Specified path does not exist:`n$_"
}
else {
return $true
}
})]
[String]
$DownloadDirectory,
[Parameter(Mandatory = $true)]
[ValidateScript({
$id = $_
$id -ge 0
if (Invoke-Command -ScriptBlock {qm status $id 2>/dev/null}) {
throw "VM with ID: $id already exists."
}
elseif (Invoke-Command -ScriptBlock {pct status $id 2>/dev/null}) {
throw "Container with ID: $id already exists."
}
else {
return $true
}
})]
[Int]
$VMID,
[Parameter(
Mandatory = $true,
HelpMessage = 'other: unspecified OS; wxp: Windows XP; w2k: Windows 2000; w2k3: Windows 2003; w2k8: Windows 2008; wvista: Windows Vista; win7: Windows 7; win8: Windows 8; win10: Windows 10; l24: Linux Kernel 2.4; l26: Linux Kernel 2.6; solaris: Solaris/OpenSolaris/OpenIndiana kernel'
)]
[ValidateSet('other', 'wxp', 'w2k', 'w2k3', 'w2k8', 'wvista', 'win7','win8', 'win10', 'l24', 'l26', 'solaris')]
[String]
$GuestOSType,
[Parameter(
Mandatory = $true,
HelpMessage = 'Example: local-lvm. This is where the guest boot disk will be stored on the Proxmox node.'
)]
[ValidateScript({
if (-not (pvesm list $_ 2>/dev/null)) {
throw "Storage volume: $_ does not exist."
}
else {
return $true
}
})]
[String]
$VMDiskStorageVolume,
[Parameter(HelpMessage = 'Example: vmbr0')]
[ValidateNotNullOrEmpty()]
[ValidateScript({
if (-not (ip link show $_)) {
throw "Network interface not found."
}
else {
return $true
}
})]
[String]
$NetworkBridge,
[Parameter(HelpMessage = 'Enter an integer between 0 and 4094')]
[ValidateRange(0,4094)]
[Int]
$VlanTag,
[Parameter(HelpMessage = 'Strictly for administrative purposes only.')]
[ValidateNotNullOrEmpty()]
[String]
$VMName,
[Parameter(HelpMessage = 'Example: 2048')]
[Int]
$MemoryMiB
)
begin {
if (-not (which unar)) {
throw "This script requires the program, unar, which is a single archive decompression tool that works on a variety or archive types.`nPlease install that program and re-run the script."
}
function Find-VMDK ($Directory) {
$files = Get-ChildItem $Directory -Recurse
$vmdk = $files | Where-Object {$_.Extension -eq '.vmdk'}
if (-not $vmdk) {
$files | ForEach-Object {
$file = $_
$type = file $file.FullName
$isArchive = $type -like '*archive*' -or $type -like '*compressed*'
if ($isArchive) {
Write-Host "Nested archive found: " -NoNewLine
Write-Host $file.FullName -ForegroundColor Green
$archiveFileFound = $file
}
}
if ($archiveFileFound) {
$subdirectory = "$Directory/temp$(Get-Random)"
unar $archiveFileFound.FullName -o $subdirectory
Find-VMDK -Directory $subdirectory
}
else {
throw "No .vmdk file found and finished recursively checking for archives without results."
}
}
else {
return $vmdk
}
}
if (-not [System.IO.Path]::EndsInDirectorySeparator($DownloadDirectory)) { $DownloadDirectory = $DownloadDirectory + '/' }
$fileName = $VulnhubURI.Segments[-1] # Define the download file name based on the URI provided.
if ($fileName -like '*.iso') { throw "Creating VMs from ISO files not yet implemented." }
$downloadPath = $DownloadDirectory + $fileName
$archiveOutputDirectory = $DownloadDirectory + "temp$(Get-Random)"
$parameterCollection = @()
$parameterCollection += "--ostype $GuestOSType"
$parameterCollection += "--storage $VMDiskStorageVolume"
if ($PSBoundParameters['NetworkBridge']) {
if ($PSBoundParameters['VlanTag']) {
$parameterCollection += "--net0 model=virtio,bridge=$NetworkBridge,firewall=0,tag=$VlanTag"
}
else {
$parameterCollection += "--net0 model=virtio,bridge=$NetworkBridge,firewall=0"
}
}
if ($PSBoundParameters['VMName']) { $parameterCollection += "--name $VMName" }
if ($PSBoundParameters['MemoryMiB']) { $parameterCollection += "--memory $MemoryMiB" }
$parameterString = $parameterCollection -join ' '
}
process {
Write-Host "[+] Downloading VM from Vulnhub. Please be patient...`n" -ForegroundColor Green
wget $VulnhubURI.ToString() -q --show-progress -O $downloadPath
$downloadedVM = Get-ChildItem $downloadPath
try {
Write-Host "[+] Decompressing archive: $downloadedVM to $archiveOutputDirectory`n" -ForegroundColor Green
Write-Host "[!] This may take a while depending on the size of the archive.`n" -ForegroundColor Yellow
unar $downloadedVM.FullName -o $archiveOutputDirectory
}
catch {
throw "Error expanding archive:`n$_"
}
try {
Write-Host "[+] Replacing any whitespace from file paths for compatibility.`n" -ForegroundColor Green
Get-ChildItem $archiveOutputDirectory -Recurse | ForEach-Object { # Arbitrarily try to remove any whitespace in file path, as this has been an issue before
$removeWhiteSpace = $_.FullName -replace ' ', '_'
if ($removeWhiteSpace -ne $_.FullName) {
Move-Item $_.FullName $removeWhiteSpace
}
}
Write-Host "[+] Searching for the .vmdk disk file(s) in $archiveOutputDirectory`n" -ForegroundColor Green
$vmDisk = Find-VMDK -Directory $archiveOutputDirectory
$vmDisk = Find-VMDK -Directory $archiveOutputDirectory # Rediscover the renamed disks
Write-Host "[+] Attempting to convert the VMDK file(s) to QCOW2 to support snapshots.`n" -ForegroundColor Green
$qcow2Disks = @()
$vmDisk | ForEach-Object {
$vmdkfile = $_
$qcow2file = $vmdkfile.FullName -replace 'vmdk', 'qcow2'
$qcow2Disks += $qcow2file
Start-Process qemu-img -ArgumentList "convert -f vmdk -O qcow2 $($vmdkfile.FullName) $qcow2file" -Wait
}
}
catch {
Get-Item $downloadPath, $archiveOutputDirectory | Remove-Item -Recurse -Force # Clean up any artifacts after error.
throw $_
}
try {
Write-Host "[+] Attempting to create the VM with the following command: qm create $VMID $parameterString.`n" -ForegroundColor Green
Start-Process qm -ArgumentList "create $VMID $parameterString" -Wait -RedirectStandardOutput /dev/null
Write-Host "[+] Attempting to import the QCOW2 file(s) as a disk.`n" -ForegroundColor Green
$qcow2Disks | ForEach-Object {
$disk = $_
Write-Host "[+] Running command: qm importdisk $VMID $disk $VMDiskStorageVolume --format qcow2`n" -ForegroundColor Green
Start-Process qm -ArgumentList "importdisk $VMID $disk $VMDiskStorageVolume --format qcow2" -Wait -RedirectStandardOutput /dev/null
}
$iteration = 0
$qcow2Disks | ForEach-Object {
Write-Host "[+] Attempting to attach the disk to the VM's SATA controller.`n" -ForegroundColor Green
Write-Host "[+] Running command: qm set $VMID --sata$iteration $($VMDiskStorageVolume):vm-$VMID-disk-$iteration`n" -ForegroundColor Green
Start-Process qm -ArgumentList "set $VMID --sata$iteration $($VMDiskStorageVolume):vm-$VMID-disk-$iteration" -Wait -RedirectStandardOutput /dev/null
$iteration++
}
Write-Host "[+] Setting sata0 as the boot device.`n" -ForegroundColor Green
Start-Process qm -ArgumentList "set $VMID --boot=`"order=sata0`"" -Wait -RedirectStandardOutput /dev/null
Write-Host "[+] All commands completed successfully`n" -ForegroundColor Green
}
catch {
throw "Command failed with the following error:`n$_"
}
}
end {
if ((Test-Path $downloadPath -ErrorAction SilentlyContinue) -or (Test-Path $archiveOutputDirectory -ErrorAction SilentlyContinue)) {
Write-Host "[+] Removing any files created by the script.`n" -ForegroundColor Green
Remove-Item $downloadPath -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
Remove-Item $archiveOutputDirectory -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
}
}
+24
View File
@@ -0,0 +1,24 @@
Install-Module -Name Corsinvest.ProxmoxVE.Api -Force
Get-Help New-PveNodesQemu -Full
get-help New-PveNodesQemu -Detailed
$ticket = Connect-PveCluster -HostsAndPorts 192.68.1.200:8006,192.168.1.200 -SkipCertificateCheck -ApiToken $Env:PveApiToken
$ret = Get-PveVersion
#Zeigt die PVE Version an
$ret.ToData() |
#Zeigt die PVE Specs an
(Get-PveNodes).ToData() | Select-Object -Property type,node,uptime,status,maxcpu,maxdisk | Out-Default
#Zeigt alle Informationen einer VM an
Get-PveVm -VmIdOrName 3101
#Zeigt alle Snpshots einer VM an
(Get-PveNodesQemuSnapshot -node cc02 -Vmid 102).ToTable()
#oder
(Get-PveVm -VmIdOrName 3101 | Get-PveNodesQemuSnapshot).ToTable()
#new VM anlegen
New-PveNodesQemu -
+45
View File
@@ -0,0 +1,45 @@
Connect-PveCluster -HostsAndPorts 192.168.1.151:8006 -SkipCertificateCheck
Get-PveNode
Get-PveVm
Get-PveAccessDomains
Get-PveAccessRoles
Get-PveNodesAptUpdate
Get-PveNodesDisks
Get-PveNodesStatus
Get-PveVersio
#wert Für NetN
$networkConfig = @{ 1 = [uri]::EscapeDataString("model=virtio,bridge=vmbr0") }
#Netadapter Setting
#Wert für Storage
$storageConfig = @{ 1 = 'local-lvm:32' }
# Storage Setting SATA, IDE, SCSI und VirtIO Block
#Wert für ISO Laufwerk
$bootableIso = @{ 1 = 'local:iso/ubuntu.iso' }
# Sample
#New-PveNodesQemu -Node $node -Vmid 105 -Memory 2048 -ScsiN $storageConfig -IdeN $bootableIso -NetN $networkConfig
#Versions Abfrage
$ret = Get-PveVersion
$ret.Response.data
New-PveNodesQemu -PveTicket $ticket -Vmid 101 -Node "Proxmox-Hyber-V" -Description "Posh Erstellt" -Cores 4 -Memory 1024 -Agent enable -Sata0':'23
New-PveNodesQemu -PveTicket $ticket -Node "Proxmox-Hyber-V" -Vmid 101 -Cores 4
New-PveNodesQemu -PveTicket $ticket -Node "Proxmox-Hyber-V" -Vmid 102 -Cores 4 -Memory "1024"
New-PveNodesQemu -PveTicket $ticket -Node "Proxmox-Hyber-V" -Vmid 103 -Cores 4 -Memory "1024" -SataN $storageConfig
Set-PveNodesQemuConfig -PveTicket $ticket -Node 101 -Acpi:$true -Agent "Enable"
$ticket = (Connect-PveCluster -HostsAndPorts 192.168.1.151:8006 -SkipCertificateCheck | Where-Object Ticket)
$id = Read-Host "Bitte die VM ID eingeben! : "
Set-PveNodesQemuConfig -vmid $id -PveTicket $ticket -kvm:$true -Agent 'Enable' -SataN $storageConfig
get-help Set-PveNodesQemuConfig -Detailed
+75
View File
@@ -0,0 +1,75 @@
<#
Variablenblock
#>
#
$Global:pvecredential = Get-Credential -UserName "root" -Message "Anmeldung am Proxmox"
$pveUsername = ($Global:pvecredential).UserName
$pvePwENcrypt = ConvertFrom-SecureString -SecureString ($Global:pvecredential).Password
$hostpve = Read-Host 'Bitte die IP des Servers eingeben: '
$ticket = (Connect-PveCluster -HostsAndPorts $($hostpve)':8006' -Credentials $Global:pvecred -SkipCertificateCheck | Where-Object Ticket)
$vers = $PSVersionTable.PSVersion.Major
if ($vers -gt '5') {
Write-Host "
Mit Ihrer Version $vers kann das Script ausgeführt werden.
"
}
else {
Write-Host "Mit Ihrer Powershell Version kann dieses Script nicht ausgeführt werden."
}
function newvm {
param (
[Parameter(Mandatory=$true)]
[ValidateSet("SataN","IdeN","ScsiN")]$hddtype
)
$vmid = Read-Host "Geben Sie die VM ID ein : "
$core = Read-Host "Wieviele Core's soll die VM haben : "
$mem = Read-Host "Wieviel RAM soll die VM haben, einbae in MB: "
$hdd = Read-Host "Wie groß soll die Festplatte sein, eingabe in GB: "
$hddtype = Read-Host "Was für ein HDD Typ soll es sein (SataN, Ide, ScsiN): "
$hddlocation = Read-Host "Wo Soll die HDD liegen: "
$storageConfig = @{ 1 = "$($hddlocation):$($hdd)" }
$storageConfig
New-PveNodesQemu -PveTicket $ticket -Vmid $vmid -Description "Posh Erstellt" -Cores $core -Memory $mem -Agent "True" enable -Node "Proxmox-Hyber-V" -$($hddtype) $storageConfig
Write-Host "Function New VM"11
}
function change {
#New-PveNodesQemu -PveTicket $ticket -Vmid 101 -Description "Posh Erstellt" -Cores 4 -Memory 1024 -Agent enable -Sata0':'23 -Node "Proxmox-Hyber-V"
Write-Host "Function Change VM"
}
function delete {
#New-PveNodesQemu -PveTicket $ticket -Vmid 101 -Description "Posh Erstellt" -Cores 4 -Memory 1024 -Agent enable -Sata0':'23 -Node "Proxmox-Hyber-V"
Write-Host "Function delete VM"
}
function Show-CustomMenu
{
param (
[string]$menuname = 'Proxmox VE VM Menü'
)
Clear-Host
Write-Host "================ $menuname ================"
Write-Host "1: Wähle '1' Erstellung einer Neues VM"
Write-Host "2: Wähle '2' Ändern einer VM"
Write-Host "3: Wähle '3' Löschen einer VM"
Write-Host "x: Beenden "
}
# Menue aufrufen und Titel uebergeben
Show-CustomMenu menuname 'Proxmox VE VM Menü'
do {
$choice = Read-Host Show-CustomMenu
switch ($choice) {
1 { newvm -hddtype SataN }
2 { change }
3 { delete }
x { return }
}
} while (
$choice = "X"
)
+44
View File
@@ -0,0 +1,44 @@
#Connection to cluster user and password
Connect-PveCluster -HostsAndPorts 192.168.1.151:8006 -SkipCertificateCheck
PowerShell credential request
Proxmox VE Username and password, username formatted as user@pam, user@pve, user@yourdomain or user (default domain pam).
User: root
Password for user test: ****
#return Ticket, default set $Global:PveTicketLast
#this is useful when connections to multiple clusters are needed use parameter -SkipRefreshPveTicketLast
HostName : 192.168.190.191
Port : 8006
SkipCertificateCheck : True
Ticket : PVE:test@pam:5EFF3CCA::iXhSNb5NTgNUYznf93mBOhj8pqYvAXoecKBHCXa3coYwBWjsWO/x8TO1gIDX0yz9nfHuvY3alJ0+Ew5AouOTZlZl3NODO9Cp4Hl87qnzhsz4wvoYEzvS1NUOTBekt+yAa68jdbhP
OzhOd8ozEEQIK7Fw2lOSa0qBFUTZRoMtnCnlsjk/Nn3kNEnZrkHXRGm46fA+asprvr0nslLxJgPGh94Xxd6jpNDj+xJnp9u6W3PxiAojM9g7IRurbp7ZCJvAgHbA9FqxibpgjaVm4NCd8LdkLDgCROxgYCjI3eR
gjkDvu1P7lLjK9JxSzqnCWWD739DT3P3bW+Ac3SyVqTf8sw==
CSRFPreventionToken : 5EFF3CCA:Cu0NuFiL6CkhFdha2V+HHigMQPk
#Connection to cluster using Api Token
Connect-PveCluster -HostsAndPorts 192.168.190.191:8006,192.168.190.192 -SkipCertificateCheck -ApiToken root@pam!qqqqqq=8a8c1cd4-d373-43f1-b366-05ce4cb8061f
HostName : 192.168.190.191
Port : 8006
SkipCertificateCheck : True
Ticket :
CSRFPreventionToken :
ApiToken : root@pam!qqqqqq=8a8c1cd4-d373-43f1-b366-05ce4cb8061f
#For disable output call Connect-PveCluster > $null
#Get version
$ret = Get-PveVersion
#$ret return a class PveResponse
#Show data
$ret.Response.data
#repoid release keyboard version
#------ ------- -------- -------
#d0ec33c6 15 it 5.4
#Show data 2
$ret.ToTable()
repoid release keyboard version
------ ------- -------- -------
d0ec33c6 15 it 5.4
View File
+2
View File
@@ -0,0 +1,2 @@
tcn 192.168.1.200
Test-Connection 192.168.1.200; 192.168.1.199; 192.168.1.198
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
# Parameter
$excelPath = "C:\Pfad\zu\hosts.xlsx"
$isoPath = "C:\Pfad\zu\original.iso"
$tempPath = "C:\Temp\IsoContents"
$newIsoPath = "C:\Pfad\zu\custom.iso"
# Import-Excel Modul laden
Import-Module ImportExcel
# Excel-Daten lesen
$hostsData = Import-Excel -Path $excelPath
# ISO mounten und Dateien kopieren
Mount-DiskImage -ImagePath $isoPath
$disk = Get-DiskImage -ImagePath $isoPath
$volume = Get-Volume -DiskImage $disk
Copy-Item -Path "$($volume.DriveLetter):\*" -Destination $tempPath -Recurse
Dismount-DiskImage -ImagePath $isoPath
# ks.cfg aktualisieren
$ksPath = "$tempPath\ks.cfg"
$configContent = Get-Content -Path $ksPath
foreach ($host in $hostsData) {
$hostname = $host.Hostname
$ip = $host.'IP-Adresse'
$netmask = $host.Netzmaske
$gateway = $host.Gateway
$dns = $host.'DNS-Server'
$username = $host.Benutzername
$password = $host.Passwort
$timezone = $host.Zeitzone
$partitioning = $host.Partitionierung
$configContent = $configContent -replace "<hostname_placeholder>", $hostname
$configContent = $configContent -replace "<ip_placeholder>", $ip
$configContent = $configContent -replace "<netmask_placeholder>", $netmask
$configContent = $configContent -replace "<gateway_placeholder>", $gateway
$configContent = $configContent -replace "<dns_placeholder>", $dns
$configContent = $configContent -replace "<password_placeholder>", $password
$configContent = $configContent -replace "<timezone_placeholder>", $timezone
$configContent = $configContent -replace "<partitioning_placeholder>", $partitioning
}
$configContent | Set-Content -Path $ksPath
# Neue ISO erstellen
& oscdimg -n -m -b"$tempPath\boot\etfsboot.com" $tempPath $newIsoPath
Write-Host "Neue ISO wurde erstellt: $newIsoPath"
+163
View File
@@ -0,0 +1,163 @@
# Import necessary modules
Import-Module Corsinvest.ProxmoxVE.Api
Import-Module ImportExcel
Add-Type -AssemblyName System.Windows.Forms
# Proxmox connection info
$ProxmoxURL = "https://your-proxmox-url:8006"
$ProxmoxUser = "root"
$ProxmoxPassword = "P@ssw0rd"
$ProxmoxRealm = "pam"
# Connect to Proxmox
$credentials = New-Object System.Management.Automation.PSCredential ($ProxmoxUser, (ConvertTo-SecureString $ProxmoxPassword -AsPlainText -Force))
$null = Connect-PveCluster -Server $ProxmoxURL -User $ProxmoxUser -Realm $ProxmoxRealm -Credential $credentials
# Read Excel data
$excelPath = "C:\path\to\depl_systems.xlsx"
$hostsData = Import-Excel -Path $excelPath
# Function to get VMs from Proxmox
function Get-ProxmoxVMs {
$vms = Get-PveVMList
return $vms
}
# Function to check missing VMs
function Get-MissingVMs {
$proxmoxVMs = Get-ProxmoxVMs
$missingVMs = @()
foreach ($host in $hostsData) {
$vmName = $host.'VM-Name'
if ($proxmoxVMs | Where-Object { $_.name -eq $vmName } -eq $null) {
$missingVMs += $host
}
}
return $missingVMs
}
# Function to get node usage
function Get-NodeUsage {
param ($node)
$usage = Get-PveNodeStatus -NodeName $node
return @{
Node = $node
MaxMem = $usage.memory.total
Mem = $usage.memory.used
MaxDisk = $usage.rootfs.total
Disk = $usage.rootfs.used
}
}
# Function to create and start VM
function Create-VM {
param (
$node,
$vmId,
$vmName,
$vmCores,
$vmMemory,
$vmDiskSize,
$isoFile
)
$params = @{
NodeName = $node
VMID = $vmId
Name = $vmName
Cores = $vmCores
Memory = $vmMemory
DiskSize = $vmDiskSize
ISOImage = $isoFile
}
New-PveVM @params
Start-PveVM -NodeName $node -VMID $vmId
Write-Host "VM wurde auf dem Node $node erstellt und gestartet"
}
# Create GUI
$form = New-Object System.Windows.Forms.Form
$form.Text = "Proxmox VM Manager"
$form.Size = New-Object System.Drawing.Size(600, 400)
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Size = New-Object System.Drawing.Size(560, 300)
$listBox.Location = New-Object System.Drawing.Point(10, 10)
$buttonCheck = New-Object System.Windows.Forms.Button
$buttonCheck.Text = "Check Missing VMs"
$buttonCheck.Size = New-Object System.Drawing.Size(120, 30)
$buttonCheck.Location = New-Object System.Drawing.Point(10, 320)
$buttonCheck.Add_Click({
$missingVMs = Get-MissingVMs
$listBox.Items.Clear()
if ($missingVMs.Count -eq 0) {
$listBox.Items.Add("Es fehlen keine VMs.")
} else {
foreach ($vm in $missingVMs) {
$listBox.Items.Add("$($vm.'VM-Name')")
}
}
})
$buttonDeploy = New-Object System.Windows.Forms.Button
$buttonDeploy.Text = "Deploy Missing VMs"
$buttonDeploy.Size = New-Object System.Drawing.Size(120, 30)
$buttonDeploy.Location = New-Object System.Drawing.Point(140, 320)
$buttonDeploy.Add_Click({
$missingVMs = Get-MissingVMs
if ($missingVMs.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show("Es fehlen keine VMs.")
return
}
foreach ($hostData in $missingVMs) {
# Create custom ISO for host (implement your own logic)
$customIsoPath = "C:\path\to\custom.iso"
# Upload ISO to Proxmox
$isoUploadPath = "/var/lib/vz/template/iso/custom.iso"
$null = Upload-PveFile -NodeName $bestNode.Node -ContentType iso -FilePath $customIsoPath -Storage local
# Get cluster nodes and their usage
$nodes = Get-PveNode
$nodeUsages = @()
foreach ($node in $nodes) {
$nodeUsages += Get-NodeUsage -node $node.name
}
# Select the best node based on available resources
$bestNode = $nodeUsages | Sort-Object {[math]::Min($_.MaxMem - $_.Mem, $_.MaxDisk - $_.Disk)} -Descending | Select-Object -First 1
Write-Host "Der beste Node zur Erstellung der VM ist: $($bestNode.Node)"
# VM creation parameters
$vmId = $hostData.'VM-ID'
$vmName = $hostData.'VM-Name'
$vmCores = $hostData.'Cores'
$vmMemory = $hostData.'Memory'
$vmDiskSize = $hostData.'Disk-Size'
$isoFile = "local:iso/custom.iso"
# Create and start the VM
Create-VM -node $bestNode.Node -vmId $vmId -vmName $vmName -vmCores $vmCores -vmMemory $vmMemory -vmDiskSize $vmDiskSize -isoFile $isoFile
}
[System.Windows.Forms.MessageBox]::Show("Alle fehlenden VMs wurden erstellt.")
})
$form.Controls.Add($listBox)
$form.Controls.Add($buttonCheck)
$form.Controls.Add($buttonDeploy)
# Load existing VMs into the listbox
$listBox.Items.Clear()
$vms = Get-ProxmoxVMs
foreach ($vm in $vms) {
$listBox.Items.Add($vm.name)
}
$form.ShowDialog()
+23
View File
@@ -0,0 +1,23 @@
# Verbindung zu Linux-System herstellen
$session = New-PSSession -HostName "192.168.1.249" -UserName "root" -Password "P@ssw0rd"
# Benutzer anlegen
Invoke-Command -Session $session -ScriptBlock {
sudo useradd -m -s /bin/bash michael
}
# Gruppe anlegen
Invoke-Command -Session $session -ScriptBlock {
sudo groupadd global
}
# Benutzer zur Gruppe hinzufügen
Invoke-Command -Session $session -ScriptBlock {
sudo usermod -aG global michael
}
# Passwort für den Benutzer setzen
$password = ConvertTo-SecureString "<Passwort>" -AsPlainText -Force
Invoke-Command -Session $session -ScriptBlock {
echo "<Benutzername>:<Passwort>" | sudo chpasswd
}
+50
View File
@@ -0,0 +1,50 @@
# Import necessary modules
Import-Module Corsinvest.ProxmoxVE.Api
Import-Module ImportExcel
# Proxmox connection info
$ProxmoxURL = "https://your-proxmox-url:8006"
$ProxmoxUser = "root"
$ProxmoxPassword = "P@ssw0rd"
$ProxmoxRealm = "pam"
# Connect to Proxmox
$credentials = New-Object System.Management.Automation.PSCredential ($ProxmoxUser, (ConvertTo-SecureString $ProxmoxPassword -AsPlainText -Force))
$null = Connect-PveCluster -Server $ProxmoxURL -User $ProxmoxUser -Realm $ProxmoxRealm -Credential $credentials
# Read Excel data
$excelPath = "/path/to/depl_systems.xlsx"
$hostsData = Import-Excel -Path $excelPath
# Function to get VMs from Proxmox
function Get-ProxmoxVMs {
$vms = Get-PveVM
return $vms
}
# Function to check missing VMs
function Get-MissingVMs {
$proxmoxVMs = Get-ProxmoxVMs
$missingVMs = @()
foreach ($host in $hostsData) {
$vmName = $host.'VM-Name'
if ($proxmoxVMs | Where-Object { $_.name -eq $vmName } -eq $null) {
$missingVMs += $host
}
}
return $missingVMs
}
# Function to get node usage
function Get-NodeUsage {
param ($node)
$usage = Get-PveNodeStatus -NodeName $node
return @{
Node = $node
MaxMem = $usage.memory.total
Mem = $usage.memory.used
MaxDisk = $usage.rootfs.total
+26
View File
@@ -0,0 +1,26 @@
# Verbindung zu Linux-System herstellen
$session = New-PSSession -HostName 192.168.1.151 -UserName 'root' -Password 'P@ssw0rd'
# Benutzer anlegen
Invoke-Command -Session $session -ScriptBlock {
sudo useradd -m -s /bin/bash ADMInst
}
# Gruppe anlegen
Invoke-Command -Session $session -ScriptBlock {
sudo groupadd deploy
}
# Benutzer zur Gruppe hinzufügen
Invoke-Command -Session $session -ScriptBlock {
sudo usermod -aG deploy ADMInst
}
# Passwort für den Benutzer setzen
$password = ConvertTo-SecureString "<Passwort>" -AsPlainText -Force
Invoke-Command -Session $session -ScriptBlock {
echo "<Benutzername>:<Passwort>" | sudo chpasswd
}
# Sitzung schließen
Remove-PSSession $session
+60
View File
@@ -0,0 +1,60 @@
{
"General": {
"SourceType": "DVD",
"DVDSource": "E:\\",
"NetworkSource": "\\\\172.68.1.1\\Sources"
},
"SQL": {
"Instance": "VEEAMSQLSERVER",
"Database": "VeeamBackup",
"Authentication": 0
},
"Paths": {
"InstallPath": "F:\\Program Files\\Veeam\\Backup and Replication",
"CatalogPath": "H:\\VBRCatalog",
"IRCache": "F:\\ProgramData\\Veeam\\Backup\\IRCache"
},
"Ports": {
"Catalog": 9393,
"Service": 9392,
"Secure": 9401,
"REST": 9419
},
"Plugins": {
"AHV": false,
"KVM": false,
"PVE": false,
"SCP": false,
"AWS": false,
"Azure": false,
"GCP": false,
"Kasten": false
}
}
+17
View File
@@ -0,0 +1,17 @@
Import-Module ".\Modules\Logging.psm1"
Import-Module ".\Modules\Configuration.psm1"
Import-Module ".\Modules\SystemCheck.psm1"
Import-Module ".\Modules\SQL.psm1"
Import-Module ".\Modules\Prerequisites.psm1"
Import-Module ".\Modules\AnswerFile.psm1"
Import-Module ".\Modules\Installer.psm1"
Import-Module ".\Modules\Report.psm1"
Initialize-Configuration
Initialize-Logging
Invoke-SystemCheck
Invoke-Prerequisites
Initialize-AnswerFile
Install-Veeam
New-InstallationReport
+247
View File
@@ -0,0 +1,247 @@
#Requires -RunAsAdministrator
<#
===========================================================================
Veeam Backup & Replication v13 Enterprise Installer
Version : 2.0
Author : ChatGPT + Benutzer
Part 1
===========================================================================
Enthält:
- Grundeinstellungen
- Konfiguration
- Logging
- Fehlerbehandlung
- Arbeitsverzeichnisse
- Initialisierung
===========================================================================
#>
$ErrorActionPreference = "Stop"
############################################################
# VERSION
############################################################
$Script:Version = "2.0"
############################################################
# VERZEICHNISSE
############################################################
$Script:WorkDir = "C:\Temp\VeeamInstall"
$Script:LogDir = Join-Path $WorkDir "Logs"
$Script:StateFile = Join-Path $WorkDir "State.json"
$Script:ResumeFlag = Join-Path $WorkDir "Resume.flag"
$Script:InstallLog = Join-Path $LogDir "Install.log"
############################################################
# INSTALLATIONSQUELLEN
############################################################
$Script:DVDSource = "E:\"
$Script:NetworkSource = "\\172.68.1.1\Sources"
############################################################
# SQL
############################################################
$Script:SQLInstance = "VEEAMSQLSERVER"
$Script:DatabaseName = "VeeamBackup"
$Script:SQLAuthentication = 0
############################################################
# INSTALLATIONSPFADE
############################################################
$Script:InstallPath = "F:\Program Files\Veeam\Backup and Replication"
$Script:CatalogPath = "H:\VBRCatalog"
$Script:IRCachePath = "F:\ProgramData\Veeam\Backup\IRCache"
############################################################
# PORTS
############################################################
$Script:GuestCatalogPort = 9393
$Script:VeeamServicePort = 9392
$Script:SecureConnectionPort = 9401
$Script:RestServicePort = 9419
############################################################
# OPTIONEN
############################################################
$Script:AutoReboot = $true
$Script:UseLicense = $false
$Script:UseServiceAccount = $false
############################################################
# PLUGINS
############################################################
$Script:Plugins = @{
AHV_INSTALL = 0
KVM_INSTALL = 0
PVE_INSTALL = 0
SCP_INSTALL = 0
AWS_INSTALL = 0
AZURE_INSTALL = 0
GCP_INSTALL = 0
KASTEN_INSTALL = 0
}
############################################################
# LOGGING
############################################################
function Write-Log {
param(
[Parameter(Mandatory)]
[string]$Message
)
$Time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$Line = "$Time - $Message"
Write-Host $Line
Add-Content `
-Path $InstallLog `
-Value $Line
}
############################################################
# FEHLER
############################################################
function Stop-Installation {
param(
[string]$Message
)
Write-Log ""
Write-Log "########################################"
Write-Log "INSTALLATION ABGEBROCHEN"
Write-Log $Message
Write-Log "########################################"
exit 1
}
############################################################
# VERZEICHNISSE
############################################################
function Initialize-Directories {
if(Test-Path $WorkDir)
{
Remove-Item `
$WorkDir `
-Recurse `
-Force
}
New-Item `
-ItemType Directory `
-Path $WorkDir `
-Force | Out-Null
New-Item `
-ItemType Directory `
-Path $LogDir `
-Force | Out-Null
}
############################################################
# STARTBANNER
############################################################
function Show-Banner {
Clear-Host
Write-Host ""
Write-Host "==============================================="
Write-Host " Veeam Backup & Replication v13"
Write-Host " Enterprise Installer"
Write-Host ""
Write-Host " Version $Version"
Write-Host "==============================================="
Write-Host ""
}
############################################################
# INITIALISIERUNG
############################################################
function Initialize-Installer {
Show-Banner
Initialize-Directories
Write-Log "======================================="
Write-Log "Installer Version $Version"
Write-Log "Computer: $env:COMPUTERNAME"
Write-Log "Benutzer: $env:USERNAME"
Write-Log "======================================="
}
+346
View File
@@ -0,0 +1,346 @@
############################################################
# PART 2
#
# Resume Manager
# Statusverwaltung
# Pending Reboot
# Registry Funktionen
############################################################
############################################################
# REGISTRY
############################################################
function Test-RegistryValue {
param(
[string]$Path,
[string]$Name
)
try{
Get-ItemProperty `
-Path $Path `
-Name $Name `
-ErrorAction Stop | Out-Null
return $true
}
catch{
return $false
}
}
function Get-RegistryValue {
param(
[string]$Path,
[string]$Name
)
try{
(Get-ItemProperty `
-Path $Path `
-Name $Name `
-ErrorAction Stop).$Name
}
catch{
return $null
}
}
############################################################
# STATUSDATEI
############################################################
function Save-State {
param(
[string]$Step
)
$State = [PSCustomObject]@{
Version = $Version
Computer = $env:COMPUTERNAME
Date = Get-Date
Step = $Step
}
$State |
ConvertTo-Json |
Set-Content `
-Path $StateFile `
-Encoding UTF8
Write-Log "Status gespeichert ($Step)"
}
############################################################
function Load-State {
if(!(Test-Path $StateFile))
{
return $null
}
try{
Get-Content `
$StateFile `
-Raw |
ConvertFrom-Json
}
catch{
return $null
}
}
############################################################
function Remove-State {
if(Test-Path $StateFile)
{
Remove-Item `
$StateFile `
-Force
Write-Log "Statusdatei entfernt"
}
}
############################################################
# RESUME FLAG
############################################################
function Set-ResumeFlag {
New-Item `
-ItemType File `
-Path $ResumeFlag `
-Force |
Out-Null
Write-Log "Resume Flag gesetzt"
}
############################################################
function Clear-ResumeFlag {
if(Test-Path $ResumeFlag)
{
Remove-Item `
$ResumeFlag `
-Force
Write-Log "Resume Flag entfernt"
}
}
############################################################
# PENDING REBOOT
############################################################
function Test-PendingReboot {
Write-Log "Prüfe Pending Reboot"
$Pending = $false
if(Test-Path `
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending")
{
$Pending = $true
}
if(Test-Path `
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired")
{
$Pending = $true
}
if(Test-RegistryValue `
"HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" `
"PendingFileRenameOperations")
{
$Pending = $true
}
if($Pending)
{
Write-Log "Neustart erforderlich"
}
else
{
Write-Log "Kein Neustart erforderlich"
}
return $Pending
}
############################################################
# SCHEDULED TASK
############################################################
function Register-ResumeTask {
Write-Log "Erstelle Resume Task"
$Action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-ExecutionPolicy Bypass -File `"$PSCommandPath`" -Resume"
$Trigger = New-ScheduledTaskTrigger `
-AtStartup
Register-ScheduledTask `
-TaskName "VeeamInstallerResume" `
-Action $Action `
-Trigger $Trigger `
-RunLevel Highest `
-Force |
Out-Null
}
############################################################
function Remove-ResumeTask {
if(Get-ScheduledTask `
-TaskName "VeeamInstallerResume" `
-ErrorAction SilentlyContinue)
{
Unregister-ScheduledTask `
-TaskName "VeeamInstallerResume" `
-Confirm:$false
Write-Log "Resume Task entfernt"
}
}
############################################################
# RESTART
############################################################
function Restart-AndResume {
Write-Log "Automatischer Neustart"
Save-State `
-Step "Resume"
Set-ResumeFlag
Register-ResumeTask
Restart-Computer `
-Force
exit
}
############################################################
# RESUME
############################################################
function Resume-Installation {
if(!(Test-Path $ResumeFlag))
{
return
}
Write-Log "Installation wird fortgesetzt"
$State = Load-State
if($null -eq $State)
{
Stop-Installation "Statusdatei beschädigt."
}
Remove-ResumeTask
Clear-ResumeFlag
Remove-State
Write-Log "Fortsetzung abgeschlossen"
}
############################################################
# STARTPARAMETER
############################################################
param(
[switch]$Resume
)
if($Resume)
{
Resume-Installation
}
+282
View File
@@ -0,0 +1,282 @@
############################################################
# PART 3
#
# Installationsquelle
# Lizenz
# SQL Prüfung
############################################################
############################################################
# INSTALLATIONSQUELLE
############################################################
function Select-InstallationSource {
Write-Host ""
Write-Host "Veeam Installationsquelle"
Write-Host "========================="
Write-Host "1 = DVD / ISO ($DVDSource)"
Write-Host "2 = Netzwerk ($NetworkSource)"
Write-Host ""
do {
$Choice = Read-Host "Quelle auswählen"
} until ($Choice -in @("1","2"))
switch($Choice)
{
"1"
{
$Script:VeeamSource = $DVDSource
}
"2"
{
Connect-NetworkSource
}
}
Write-Log "Installationsquelle: $VeeamSource"
}
############################################################
function Connect-NetworkSource {
Write-Log "Verbinde Netzwerkquelle"
$Credential = Get-Credential
if(Get-PSDrive VEEAMSRC -ErrorAction SilentlyContinue)
{
Remove-PSDrive VEEAMSRC -Force
}
New-PSDrive `
-Name VEEAMSRC `
-PSProvider FileSystem `
-Root $NetworkSource `
-Credential $Credential `
-ErrorAction Stop |
Out-Null
$Script:VeeamSource = "VEEAMSRC:\"
}
############################################################
# INSTALLER
############################################################
function Find-VeeamInstaller {
$Script:VeeamInstaller = Join-Path `
$VeeamSource `
"Setup\Silent\Veeam.Silent.Install.exe"
if(!(Test-Path $VeeamInstaller))
{
Stop-Installation "Veeam Installer wurde nicht gefunden."
}
Write-Log "Installer gefunden"
}
############################################################
# ANSWER FILE
############################################################
function Find-AnswerFile {
$Script:AnswerFileSource = Join-Path `
$VeeamSource `
"Setup\Silent\AnswerFiles\VBR\VbrAnswerFile_install.xml"
if(!(Test-Path $AnswerFileSource))
{
Stop-Installation "Antwortdatei wurde nicht gefunden."
}
Write-Log "Antwortdatei gefunden"
}
############################################################
# LIZENZ
############################################################
function Find-LicenseFile {
$Script:LicenseSource = Join-Path `
$VeeamSource `
"License\veeam.lic"
$Script:LicenseTarget = Join-Path `
$WorkDir `
"veeam.lic"
if(Test-Path $LicenseSource)
{
Copy-Item `
$LicenseSource `
$LicenseTarget `
-Force
$Script:UseLicense = $true
Write-Log "Lizenz gefunden"
}
else
{
$Script:UseLicense = $false
Write-Log "Community Edition"
}
}
############################################################
# SQL
############################################################
function Initialize-SQL {
$Script:SQLServer = $env:COMPUTERNAME
$Script:SQLConnection = "$SQLServer\$SQLInstance"
}
############################################################
function Test-SQLService {
Write-Log "Prüfe SQL Dienst"
$ServiceName = "MSSQL`$$SQLInstance"
$Service = Get-Service `
-Name $ServiceName `
-ErrorAction SilentlyContinue
if(!$Service)
{
Stop-Installation `
"SQL Instanz '$SQLInstance' wurde nicht gefunden."
}
if($Service.Status -ne "Running")
{
Stop-Installation `
"SQL Dienst läuft nicht."
}
Write-Log "SQL Dienst OK"
}
############################################################
function Test-SQLConnectivity {
Write-Log "Prüfe SQL Verbindung"
try{
Add-Type -AssemblyName System.Data
$Connection = New-Object `
System.Data.SqlClient.SqlConnection
$Connection.ConnectionString =
"Server=$SQLConnection;" +
"Integrated Security=True;" +
"Connection Timeout=5;"
$Connection.Open()
$Connection.Close()
Write-Log "SQL Verbindung erfolgreich"
}
catch{
Stop-Installation `
"Keine Verbindung zu $SQLConnection möglich.`n$($_.Exception.Message)"
}
}
############################################################
# VEEAM BEREITS INSTALLIERT?
############################################################
function Test-VeeamInstalled {
Write-Log "Prüfe vorhandene Installation"
$Service = Get-Service `
-Name "VeeamBackupSvc" `
-ErrorAction SilentlyContinue
if($Service)
{
Stop-Installation `
"Veeam Backup & Replication ist bereits installiert."
}
Write-Log "Keine vorhandene Installation"
}
############################################################
# GESAMTPRÜFUNG
############################################################
function Initialize-InstallationSource {
Select-InstallationSource
Find-VeeamInstaller
Find-AnswerFile
Find-LicenseFile
Initialize-SQL
Test-SQLService
Test-SQLConnectivity
Test-VeeamInstalled
}
+471
View File
@@ -0,0 +1,471 @@
############################################################
# PART 4.1
#
# PART 4.1 Betriebssystem prüfen
############################################################
function Test-OperatingSystem {
Write-Log "Prüfe Betriebssystem"
try {
$OS = Get-CimInstance Win32_OperatingSystem
}
catch {
Stop-Installation "Betriebssystem konnte nicht ermittelt werden."
}
Write-Log "Betriebssystem : $($OS.Caption)"
Write-Log "Version : $($OS.Version)"
Write-Log "Build : $($OS.BuildNumber)"
if($OS.ProductType -ne 3)
{
Stop-Installation "Dieses Script unterstützt nur Windows Server."
}
switch -Regex ($OS.Caption)
{
"2022"
{
Write-Log "Windows Server 2022 erkannt."
}
"2025"
{
Write-Log "Windows Server 2025 erkannt."
}
default
{
Stop-Installation "Nicht unterstütztes Betriebssystem."
}
}
}
############################################################
# PART 4.2
#
# PART 4.2 PowerShell-Version prüfen
############################################################
function Test-PowerShellVersion {
Write-Log "Prüfe PowerShell"
$PSVersion = $PSVersionTable.PSVersion
Write-Log "PowerShell Version: $PSVersion"
if($PSVersion.Major -lt 5)
{
Stop-Installation "PowerShell 5.1 oder höher wird benötigt."
}
if($PSVersion.Major -ge 7)
{
Write-Log "PowerShell 7 erkannt."
}
else
{
Write-Log "PowerShell 5.x erkannt."
}
}
############################################################
# PART 4.3
#
# PART 4.3 CPU prüfen
############################################################
function Test-CPU {
Write-Log "Prüfe CPU"
$CPU = Get-CimInstance Win32_Processor
Write-Log "CPU : $($CPU.Name)"
Write-Log "Kerne : $($CPU.NumberOfCores)"
Write-Log "Logische CPUs : $($CPU.NumberOfLogicalProcessors)"
if($CPU.NumberOfLogicalProcessors -lt 2)
{
Stop-Installation "Mindestens 2 logische Prozessoren erforderlich."
}
}
############################################################
# PART 4.4
#
# PART 4.4 RAM prüfen
############################################################
function Test-Memory {
Write-Log "Prüfe Arbeitsspeicher"
$RAM = (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory
$RAMGB = [Math]::Round($RAM / 1GB,2)
Write-Log "RAM : $RAMGB GB"
if($RAMGB -lt 8)
{
Stop-Installation "Mindestens 8 GB RAM erforderlich."
}
}
############################################################
# PART 4.5
#
# PART 4.5 Laufwerke prüfen
############################################################
function Test-Drive {
param(
[Parameter(Mandatory)]
[string]$DriveLetter,
[Parameter(Mandatory)]
[int]$MinimumFreeGB
)
Write-Log "Prüfe Laufwerk $DriveLetter"
$Drive = Get-CimInstance Win32_LogicalDisk |
Where-Object DeviceID -eq $DriveLetter
if(!$Drive)
{
Stop-Installation "Laufwerk $DriveLetter existiert nicht."
}
$Free = [Math]::Round($Drive.FreeSpace / 1GB,2)
Write-Log "Freier Speicher : $Free GB"
if($Free -lt $MinimumFreeGB)
{
Stop-Installation "Zu wenig Speicher auf $DriveLetter."
}
}
############################################################
# PART 4.6
#
# PART 4.6 Installationspfade prüfen
############################################################
function Test-InstallationPaths {
Write-Log "Prüfe Installationslaufwerke"
Test-Drive "C:" 10
Test-Drive "F:" 20
Test-Drive "H:" 20
}
############################################################
# PART 4.7
#
# PART 4.7 Pending Reboot
############################################################
function Test-PendingReboot {
Write-Log "Prüfe Pending Reboot"
$Pending = $false
if(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending")
{
$Pending = $true
}
if(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired")
{
$Pending = $true
}
if(Get-ItemProperty `
"HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" `
-ErrorAction SilentlyContinue |
Select-Object -ExpandProperty PendingFileRenameOperations `
-ErrorAction SilentlyContinue)
{
$Pending = $true
}
if($Pending)
{
Write-Log "Pending Reboot erkannt."
Restart-AndResume
}
Write-Log "Kein Pending Reboot."
}
############################################################
# PART 4.8
#
# PART 4.8 Gesamter Systemcheck
############################################################
function Invoke-SystemCheck {
Write-Log ""
Write-Log "===================================="
Write-Log "Systemprüfung gestartet"
Write-Log "===================================="
Test-OperatingSystem
Test-PowerShellVersion
Test-CPU
Test-Memory
Test-InstallationPaths
Test-PendingReboot
Write-Log "Systemprüfung erfolgreich abgeschlossen."
}
############################################################
# PART 4.9
#
# SQL Server Prüfung
#
# SQL Server 2022 Standard
# Instanz VEEAMSQLSERVER
############################################################
function Test-SQLInstance {
Write-Log "===================================="
Write-Log "Prüfe SQL Instanz"
Write-Log "===================================="
#
# Variablen
#
$SQLInstanceName = "VEEAMSQLSERVER"
$SQLServerName = $env:COMPUTERNAME
$SQLConnection = "$SQLServerName\$SQLInstanceName"
Write-Log "SQL Server : $SQLConnection"
#
# SQL Dienst prüfen
#
$ServiceName = "MSSQL`$$SQLInstanceName"
$SQLService = Get-Service `
-Name $ServiceName `
-ErrorAction SilentlyContinue
if(!$SQLService)
{
Stop-Installation `
"SQL Instanz $SQLInstanceName wurde nicht gefunden."
}
Write-Log "SQL Dienst gefunden"
Write-Log "Status: $($SQLService.Status)"
if($SQLService.Status -ne "Running")
{
Stop-Installation `
"SQL Dienst läuft nicht."
}
#
# SQL Verbindung testen
#
Write-Log "Teste SQL Verbindung"
try
{
Add-Type -AssemblyName System.Data
$ConnectionString = @"
Server=$SQLConnection;
Integrated Security=True;
Database=master;
Connection Timeout=10;
"@
$Connection = New-Object `
System.Data.SqlClient.SqlConnection
$Connection.ConnectionString =
$ConnectionString
$Connection.Open()
Write-Log "SQL Verbindung erfolgreich"
#
# SQL Version lesen
#
$Command = $Connection.CreateCommand()
$Command.CommandText =
"SELECT SERVERPROPERTY('ProductVersion'),
SERVERPROPERTY('Edition'),
SERVERPROPERTY('ProductLevel')"
$Reader = $Command.ExecuteReader()
while($Reader.Read())
{
$SQLVersion = $Reader.GetValue(0)
$SQLEdition = $Reader.GetValue(1)
$SQLLevel = $Reader.GetValue(2)
Write-Log "SQL Version : $SQLVersion"
Write-Log "Edition : $SQLEdition"
Write-Log "Level : $SQLLevel"
}
$Reader.Close()
#
# Datenbank prüfen
#
$Command = $Connection.CreateCommand()
$Command.CommandText =
@"
SELECT name
FROM sys.databases
WHERE name='VeeamBackup'
"@
$Result = $Command.ExecuteScalar()
if($Result)
{
Write-Log "VeeamBackup Datenbank vorhanden"
}
else
{
Write-Log "VeeamBackup Datenbank wird durch Veeam Setup erstellt"
}
#
# Login Rechte prüfen
#
$Command.CommandText =
@"
SELECT IS_SRVROLEMEMBER('sysadmin')
"@
$SysAdmin =
$Command.ExecuteScalar()
if($SysAdmin -eq 1)
{
Write-Log "Installationskonto besitzt SQL Sysadmin Rechte"
}
else
{
Write-Log "WARNUNG: Konto besitzt keine SQL Sysadmin Rolle"
}
$Connection.Close()
}
catch
{
Stop-Installation `
"SQL Verbindung fehlgeschlagen:`n$($_.Exception.Message)"
}
Write-Log "SQL Prüfung erfolgreich"
}
+205
View File
@@ -0,0 +1,205 @@
############################################################
# PART 5.1
#
# Part 5.1 .NET Framework prüfen
############################################################
function Test-DotNetFramework {
Write-Log "Prüfe .NET Framework"
$RegPath = "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"
if(!(Test-Path $RegPath))
{
Stop-Installation ".NET Framework wurde nicht gefunden."
}
$Release = (Get-ItemProperty $RegPath).Release
Write-Log ".NET Release : $Release"
if($Release -lt 528040)
{
Stop-Installation ".NET Framework 4.8 oder höher wird benötigt."
}
Write-Log ".NET Framework OK"
}
############################################################
# PART 5.2
#
# Part 5.2 Visual C++ Redistributables prüfen
############################################################
function Test-VisualCRedistributables {
Write-Log "Prüfe Visual C++ Redistributables"
$VC = Get-ItemProperty `
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*,
HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* `
-ErrorAction SilentlyContinue |
Where-Object {
$_.DisplayName -like "*Microsoft Visual C++*"
}
if(!$VC)
{
Write-Log "Keine Visual C++ Redistributables gefunden."
Write-Log "Werden während der Veeam Installation installiert."
return
}
foreach($Item in $VC)
{
Write-Log "$($Item.DisplayName) $($Item.DisplayVersion)"
}
}
############################################################
# PART 5.3
#
# Part 5.3 Installationspfade vorbereiten
############################################################
function Initialize-InstallDirectories {
Write-Log "Erstelle Installationsverzeichnisse"
$Folders = @(
$InstallPath,
$CatalogPath,
$IRCachePath
)
foreach($Folder in $Folders)
{
if(!(Test-Path $Folder))
{
New-Item `
-ItemType Directory `
-Path $Folder `
-Force |
Out-Null
Write-Log "Ordner erstellt: $Folder"
}
else
{
Write-Log "Ordner vorhanden: $Folder"
}
}
}
############################################################
# PART 5.4
#
# Part 5.4 Schreibtest
############################################################
function Test-WritePermissions {
Write-Log "Prüfe Schreibrechte"
foreach($Folder in @($InstallPath,$CatalogPath,$IRCachePath))
{
$TestFile = Join-Path $Folder "WriteTest.tmp"
try
{
"TEST" | Set-Content $TestFile
Remove-Item $TestFile -Force
Write-Log "$Folder beschreibbar."
}
catch
{
Stop-Installation "Keine Schreibrechte auf $Folder."
}
}
}
############################################################
# PART 5.5
#
# Part 5.5 Ports prüfen
############################################################
function Test-Ports {
Write-Log "Prüfe benötigte Ports"
$Ports = @(
$VeeamServicePort,
$GuestCatalogPort,
$SecureConnectionPort,
$RestServicePort
)
foreach($Port in $Ports)
{
$Connection = Get-NetTCPConnection `
-State Listen `
-ErrorAction SilentlyContinue |
Where-Object LocalPort -eq $Port
if($Connection)
{
Write-Log "WARNUNG: Port $Port ist bereits belegt."
}
else
{
Write-Log "Port $Port verfügbar."
}
}
}
############################################################
# PART 5.6
#
# Part 5.6 Windows Firewall prüfen
############################################################
function Test-Firewall {
Write-Log "Prüfe Windows Firewall"
$Profiles = Get-NetFirewallProfile
foreach($Profile in $Profiles)
{
Write-Log "$($Profile.Name): Enabled=$($Profile.Enabled)"
}
}
############################################################
# PART 5.7
#
# Part 5.7 Voraussetzungen prüfen
############################################################
function Invoke-Prerequisites {
Write-Log ""
Write-Log "===================================="
Write-Log "Prüfung der Voraussetzungen"
Write-Log "===================================="
Test-DotNetFramework
Test-VisualCRedistributables
Initialize-InstallDirectories
Test-WritePermissions
Test-Ports
Test-Firewall
Write-Log "Voraussetzungen erfolgreich geprüft."
}
+220
View File
@@ -0,0 +1,220 @@
############################################################
# PART 6.1
#
# AnswerFile kopieren
############################################################
function Copy-AnswerFile {
Write-Log "Kopiere Antwortdatei"
$Script:AnswerFile = Join-Path `
$WorkDir `
"VbrAnswerFile_install.xml"
if(Test-Path $AnswerFile)
{
Remove-Item `
$AnswerFile `
-Force
}
Copy-Item `
-Path $AnswerFileSource `
-Destination $AnswerFile `
-Force
if(!(Test-Path $AnswerFile))
{
Stop-Installation "Antwortdatei konnte nicht kopiert werden."
}
attrib -R $AnswerFile
Write-Log "Antwortdatei erfolgreich kopiert"
}
############################################################
# PART 6.2
#
# Part 6.2 XML laden
############################################################
function Open-AnswerFile {
Write-Log "Lade XML"
try
{
[xml]$Script:AnswerXML =
Get-Content `
$AnswerFile `
-Encoding UTF8
}
catch
{
Stop-Installation "XML konnte nicht geladen werden."
}
}
############################################################
# PART 6.3
#
# Part 6.3 XML-Eigenschaft setzen
############################################################
function Set-VBRProperty {
param(
[Parameter(Mandatory)]
[string]$Name,
[Parameter(Mandatory)]
[string]$Value
)
$Node = $AnswerXML.
unattendedInstallationConfiguration.
properties.
property |
Where-Object Name -eq $Name
if(!$Node)
{
Write-Log "XML Property $Name nicht gefunden."
return
}
$Node.value = $Value
Write-Log "$Name = $Value"
}
############################################################
# PART 6.4
#
# Part 6.4 XML konfigurieren
############################################################
function Set-AnswerFileConfiguration {
Write-Log "Konfiguriere XML"
Set-VBRProperty "ACCEPT_EULA" "1"
Set-VBRProperty "ACCEPT_LICENSING_POLICY" "1"
Set-VBRProperty "ACCEPT_THIRDPARTY_LICENSES" "1"
Set-VBRProperty "ACCEPT_REQUIRED_SOFTWARE" "1"
if($UseLicense)
{
Set-VBRProperty "VBR_LICENSE_FILE" $LicenseTarget
}
else
{
Set-VBRProperty "VBR_LICENSE_FILE" "0"
}
Set-VBRProperty "VBR_SQLSERVER_INSTALL" "0"
Set-VBRProperty "VBR_SQLSERVER_ENGINE" "0"
Set-VBRProperty "VBR_SQLSERVER_SERVER" $SQLConnection
Set-VBRProperty "VBR_SQLSERVER_DATABASE" $DatabaseName
Set-VBRProperty "VBR_SQLSERVER_AUTHENTICATION" "0"
Set-VBRProperty "VBR_ENTRAID_DATABASE_INSTALL" "0"
Set-VBRProperty "INSTALLDIR" $InstallPath
Set-VBRProperty "VM_CATALOGPATH" $CatalogPath
Set-VBRProperty "VBR_IRCACHE" $IRCachePath
Set-VBRProperty "VBRC_SERVICE_PORT" $GuestCatalogPort
Set-VBRProperty "VBR_SERVICE_PORT" $VeeamServicePort
Set-VBRProperty "VBR_SECURE_CONNECTIONS_PORT" $SecureConnectionPort
Set-VBRProperty "VBR_RESTSERVICE_PORT" $RestServicePort
Set-VBRProperty "REBOOT_IF_REQUIRED" "$RebootRequired"
foreach($Plugin in $Plugins.Keys)
{
Set-VBRProperty `
$Plugin `
"$($Plugins[$Plugin])"
}
}
############################################################
# PART 6.5
#
# Part 6.5 XML validieren
############################################################
function Test-AnswerFile {
Write-Log "Prüfe XML"
if(!$AnswerXML.unattendedInstallationConfiguration)
{
Stop-Installation "Ungültige XML."
}
if(!$AnswerXML.unattendedInstallationConfiguration.properties)
{
Stop-Installation "XML Properties fehlen."
}
Write-Log "XML erfolgreich geprüft."
}
############################################################
# PART 6.6
#
# Part 6.6 XML speichern
############################################################
function Save-AnswerFile {
Write-Log "Speichere XML"
try
{
$Writer = New-Object System.Xml.XmlTextWriter(
$AnswerFile,
[System.Text.Encoding]::UTF8
)
$Writer.Formatting = "Indented"
$AnswerXML.Save($Writer)
$Writer.Close()
Write-Log "Antwortdatei gespeichert"
}
catch
{
Stop-Installation "Antwortdatei konnte nicht gespeichert werden.`n$($_.Exception.Message)"
}
}
############################################################
# PART 6.7
#
# Part 6.7 Gesamtablauf
############################################################
function Initialize-AnswerFile {
Copy-AnswerFile
Open-AnswerFile
Set-AnswerFileConfiguration
Test-AnswerFile
Save-AnswerFile
}
+400
View File
@@ -0,0 +1,400 @@
############################################################
# PART 7.1
#
# Veeam LogManager
############################################################
function Copy-VeeamSetupLogs {
Write-Log "Sichere Veeam Setup Logs"
$Source = "C:\ProgramData\Veeam\Setup\Temp"
$Destination = Join-Path `
$LogDir `
"VeeamSetup"
if(!(Test-Path $Source))
{
Write-Log "Keine Setup Logs gefunden."
return
}
if(Test-Path $Destination)
{
Remove-Item `
$Destination `
-Recurse `
-Force
}
Copy-Item `
$Source `
$Destination `
-Recurse `
-Force
Write-Log "Setup Logs kopiert."
}
############################################################
# PART 7.2
#
# Part 7.2 Logdatei suchen
############################################################
function Get-LatestSetupLog {
$Folder = Join-Path `
$LogDir `
"VeeamSetup"
if(!(Test-Path $Folder))
{
return $null
}
Get-ChildItem `
$Folder `
-Recurse `
-Filter *.log |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
}
############################################################
# PART 7.3#
#
# Part 7.3 Logdatei analysieren
############################################################
function Analyze-VeeamLog {
param(
[string]$LogFile
)
if(!(Test-Path $LogFile))
{
Write-Log "Keine Logdatei vorhanden."
return
}
Write-Log "Analysiere Logdatei"
$Content = Get-Content `
$LogFile `
-ErrorAction SilentlyContinue
foreach($Line in $Content)
{
if($Line -match "SQL")
{
Write-Log "SQL Hinweis: $Line"
}
if($Line -match "Access denied")
{
Write-Log "Berechtigungsproblem: $Line"
}
if($Line -match "Return value 3")
{
Write-Log "MSI Fehler erkannt."
}
if($Line -match "failed")
{
Write-Log $Line
}
if($Line -match "Exception")
{
Write-Log $Line
}
}
}
############################################################
# PART 7.4
#
# PART 7.4 ExitCode analysieren
############################################################
function Analyze-ExitCode {
param(
[int]$ExitCode
)
Write-Log "Installer ExitCode : $ExitCode"
switch($ExitCode)
{
0
{
Write-Log "Installation erfolgreich."
}
3010
{
Write-Log "Neustart erforderlich."
}
1603
{
Write-Log "Fatal Error"
Copy-VeeamSetupLogs
$Log = Get-LatestSetupLog
if($Log)
{
Analyze-VeeamLog `
$Log.FullName
}
}
default
{
Write-Log "Unbekannter ExitCode"
Copy-VeeamSetupLogs
}
}
}
############################################################
# PART 7.5
#
# PART 7.5 Veeam Dienste prüfen
############################################################
function Test-VeeamServices {
Write-Log "Prüfe Veeam Dienste"
$Services = @(
"VeeamBackupSvc",
"VeeamBrokerSvc",
"VeeamMountSvc"
)
foreach($Service in $Services)
{
$S = Get-Service `
$Service `
-ErrorAction SilentlyContinue
if(!$S)
{
Write-Log "$Service nicht installiert."
continue
}
Write-Log "$($S.Name) : $($S.Status)"
}
}
############################################################
# PART 7.6
#
# PART 7.6 Version prüfen
############################################################
function Get-VeeamVersion {
$Exe =
Join-Path `
$InstallPath `
"Backup\Veeam.Backup.Service.exe"
if(Test-Path $Exe)
{
$Version =
(Get-Item $Exe).VersionInfo.ProductVersion
Write-Log "Veeam Version : $Version"
}
}
############################################################
# PART 7.7
#
# Veeam Installation Engine
############################################################
function Install-Veeam {
Write-Log "======================================="
Write-Log "Starte Veeam Installation"
Write-Log "======================================="
$Arguments = @(
"/AnswerFile"
"`"$AnswerFile`""
"/SkipNetworkLogonErrors"
)
$StartTime = Get-Date
Write-Log "Installationsbeginn : $StartTime"
try {
$Process = Start-Process `
-FilePath $VeeamInstaller `
-ArgumentList $Arguments `
-PassThru
}
catch {
Stop-Installation "Installer konnte nicht gestartet werden.`n$($_.Exception.Message)"
}
Write-Log "PID : $($Process.Id)"
while(!$Process.HasExited)
{
Write-Host "." -NoNewline
Start-Sleep 10
$Process.Refresh()
}
Write-Host ""
$EndTime = Get-Date
$Duration = New-TimeSpan `
-Start $StartTime `
-End $EndTime
Write-Log "Installationsende : $EndTime"
Write-Log ("Dauer : {0:hh\:mm\:ss}" -f $Duration)
Analyze-ExitCode $Process.ExitCode
if($Process.ExitCode -eq 0 -or
$Process.ExitCode -eq 3010)
{
Test-VeeamServices
Get-VeeamVersion
}
}
############################################################
# PART 7.8
#
# PART 7.8 Installationsreport
############################################################
function Show-InstallationSummary {
Write-Host ""
Write-Host "============================================="
Write-Host "Installation abgeschlossen"
Write-Host "============================================="
Write-Host ""
Write-Host "Computer"
Write-Host "--------"
Write-Host $env:COMPUTERNAME
Write-Host ""
Write-Host "SQL"
Write-Host "----"
Write-Host $SQLConnection
Write-Host ""
Write-Host "Installation"
Write-Host "-------------"
Write-Host $InstallPath
Write-Host ""
Write-Host "Catalog"
Write-Host "-------"
Write-Host $CatalogPath
Write-Host ""
Write-Host "IR Cache"
Write-Host "--------"
Write-Host $IRCachePath
Write-Host ""
Write-Host "Log"
Write-Host "---"
Write-Host "$LogDir\Install.log"
}
############################################################
# MAIN
#
# PART 7.9 Gesamtablauf
############################################################
Invoke-SystemCheck
Invoke-Prerequisites
Initialize-AnswerFile
Install-Veeam
Show-InstallationSummary

Some files were not shown because too many files have changed in this diff Show More