Initialer Import der Synology Scripts
This commit is contained in:
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+19
@@ -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"
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+44
@@ -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
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+12
@@ -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
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+25
@@ -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
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+63
@@ -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
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+15
@@ -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
|
||||
```
|
||||
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+15
@@ -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"
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+27
@@ -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
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
function Get-CredentialFromFile {
|
||||
param([string]$Path)
|
||||
|
||||
```
|
||||
if (!(Test-Path $Path)) {
|
||||
throw "Missing credential file: $Path"
|
||||
}
|
||||
|
||||
Import-Clixml -Path $Path
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+26
@@ -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 }
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+24
@@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+68
@@ -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
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+16
@@ -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
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+15
@@ -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"
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+27
@@ -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
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
function Get-CredentialFromFile {
|
||||
param([string]$Path)
|
||||
|
||||
```
|
||||
if (!(Test-Path $Path)) {
|
||||
throw "Missing credential file: $Path"
|
||||
}
|
||||
|
||||
Import-Clixml -Path $Path
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+26
@@ -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 }
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+24
@@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+68
@@ -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
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
+16
@@ -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
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
Executable
Executable
|
|
Executable
Executable
+37
@@ -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
|
||||
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Executable
+63
@@ -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
|
||||
Executable
+13119
File diff suppressed because it is too large
Load Diff
Executable
+27
@@ -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"
|
||||
}
|
||||
Executable
+45
@@ -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
|
||||
}
|
||||
Executable
+21
@@ -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"
|
||||
}
|
||||
Executable
+222
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Executable
+24
@@ -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 -
|
||||
Executable
+45
@@ -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
|
||||
|
||||
Executable
+75
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
Executable
+44
@@ -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
|
||||
Executable
Executable
+2
@@ -0,0 +1,2 @@
|
||||
tcn 192.168.1.200
|
||||
Test-Connection 192.168.1.200; 192.168.1.199; 192.168.1.198
|
||||
Executable
+2687
File diff suppressed because it is too large
Load Diff
Executable
+50
@@ -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"
|
||||
Executable
+163
@@ -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()
|
||||
Executable
+23
@@ -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
|
||||
}
|
||||
Executable
+50
@@ -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
|
||||
|
||||
Executable
+26
@@ -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
|
||||
Executable
+60
@@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+17
@@ -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
|
||||
Executable
+247
@@ -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 "======================================="
|
||||
|
||||
}
|
||||
Executable
+346
@@ -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
|
||||
|
||||
}
|
||||
Executable
+282
@@ -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
|
||||
|
||||
}
|
||||
Executable
+471
@@ -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"
|
||||
|
||||
}
|
||||
Executable
+205
@@ -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."
|
||||
|
||||
}
|
||||
Executable
+220
@@ -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
|
||||
|
||||
}
|
||||
Executable
+400
@@ -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
Reference in New Issue
Block a user