1023 lines
14 KiB
PowerShell
Executable File
1023 lines
14 KiB
PowerShell
Executable File
#Requires -RunAsAdministrator
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Unattended Installation Veeam Backup & Replication v13
|
|
mit vorhandener Microsoft SQL Server Instanz
|
|
|
|
.DESCRIPTION
|
|
Installation über DVD/ISO oder Netzwerkquelle
|
|
Verwendung einer vorhandenen MSSQL Instanz
|
|
|
|
Datenbank:
|
|
SERVER\VEEAMSQLSERVER
|
|
|
|
Version:
|
|
1.2
|
|
#>
|
|
|
|
|
|
############################################################
|
|
# GLOBAL SETTINGS
|
|
############################################################
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
Set-StrictMode -Version Latest
|
|
|
|
|
|
|
|
############################################################
|
|
# VARIABLEN
|
|
############################################################
|
|
|
|
# Installationsquellen
|
|
|
|
$DVDSource = "E:\"
|
|
|
|
$NetworkSource = "\\172.68.1.1\Sources"
|
|
|
|
|
|
|
|
# Arbeitsverzeichnis
|
|
|
|
$WorkDir = "C:\Temp\VeeamInstall"
|
|
|
|
$LogDir = "$WorkDir\Logs"
|
|
|
|
|
|
|
|
# Antwortdatei
|
|
|
|
$AnswerFileName = "VbrAnswerFile_install.xml"
|
|
|
|
$AnswerFile = "$WorkDir\$AnswerFileName"
|
|
|
|
|
|
|
|
# Lizenz
|
|
|
|
$LicenseSource = "$($DVDSource)\License\veeam.lic"
|
|
|
|
$LicenseTarget = "$WorkDir\veeam.lic"
|
|
|
|
|
|
|
|
# Server
|
|
|
|
$VeeamServerName = $env:COMPUTERNAME
|
|
|
|
|
|
|
|
# SQL
|
|
|
|
$SQLInstanceName = "VEEAMSQLSERVER"
|
|
|
|
$SQLConnection = "$VeeamServerName\$SQLInstanceName"
|
|
|
|
$DatabaseName = "VeeamBackup"
|
|
|
|
$SQLAuthentication = 0
|
|
|
|
|
|
|
|
# Pfade
|
|
|
|
$InstallPath = "F:\Program Files\Veeam\Backup and Replication"
|
|
|
|
$CatalogPath = "H:\VBRCatalog"
|
|
|
|
$IRCachePath = "F:\ProgramData\Veeam\Backup\IRCache"
|
|
|
|
|
|
|
|
# Ports
|
|
|
|
$GuestCatalogPort = 9393
|
|
|
|
$VeeamServicePort = 9392
|
|
|
|
$SecureConnectionPort = 9401
|
|
|
|
$RestServicePort = 9419
|
|
|
|
|
|
|
|
# Neustart
|
|
|
|
$RebootRequired = 0
|
|
|
|
|
|
|
|
# Plugins
|
|
|
|
$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
|
|
|
|
}
|
|
|
|
|
|
|
|
# Wird später gesetzt
|
|
|
|
$VeeamSource = ""
|
|
|
|
$VeeamInstaller = ""
|
|
|
|
$AnswerFileSource = ""
|
|
|
|
$UseLicenseFile = $false
|
|
|
|
|
|
|
|
############################################################
|
|
# FUNKTIONEN
|
|
############################################################
|
|
|
|
|
|
function Write-Log {
|
|
|
|
param(
|
|
[Parameter(Mandatory)]
|
|
[string]
|
|
$Message
|
|
)
|
|
|
|
|
|
$Time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
|
|
$Entry = "$Time - $Message"
|
|
|
|
|
|
Write-Host $Entry
|
|
|
|
|
|
if(Test-Path $LogDir)
|
|
{
|
|
|
|
Add-Content `
|
|
-Path "$LogDir\Install.log" `
|
|
-Value $Entry
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function Initialize-Directories {
|
|
|
|
|
|
Write-Log "Erstelle Arbeitsverzeichnisse"
|
|
|
|
|
|
foreach($Path in @(
|
|
$WorkDir,
|
|
$LogDir
|
|
))
|
|
{
|
|
|
|
if(!(Test-Path $Path))
|
|
{
|
|
|
|
New-Item `
|
|
-Path $Path `
|
|
-ItemType Directory `
|
|
-Force | Out-Null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function Remove-OldInstallFiles {
|
|
|
|
|
|
if(Test-Path $WorkDir)
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
Remove-Item `
|
|
-Path $WorkDir `
|
|
-Recurse `
|
|
-Force `
|
|
-ErrorAction Stop
|
|
|
|
|
|
Write-Host "Alte VeeamInstall-Dateien entfernt."
|
|
|
|
}
|
|
catch
|
|
{
|
|
|
|
Write-Host "Fehler beim Löschen: $($_.Exception.Message)"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function Select-VeeamSource {
|
|
|
|
|
|
Write-Host ""
|
|
|
|
Write-Host "Veeam Installationsquelle"
|
|
|
|
Write-Host "========================="
|
|
|
|
Write-Host "1 = DVD / ISO Quelle ($DVDSource)"
|
|
|
|
Write-Host "2 = Netzwerkquelle ($NetworkSource)"
|
|
|
|
Write-Host ""
|
|
|
|
|
|
$Choice = Read-Host "Quelle auswählen (1 oder 2)"
|
|
|
|
|
|
|
|
switch($Choice)
|
|
{
|
|
|
|
"1"
|
|
{
|
|
|
|
$script:VeeamSource = $DVDSource
|
|
|
|
|
|
Write-Host ""
|
|
|
|
Write-Host "Lokale Quelle gewählt:"
|
|
|
|
Write-Host $VeeamSource
|
|
|
|
}
|
|
|
|
|
|
"2"
|
|
{
|
|
|
|
Write-Host ""
|
|
|
|
Write-Host "Netzwerkquelle wird verwendet"
|
|
|
|
|
|
$Credential = Get-Credential
|
|
|
|
|
|
|
|
New-PSDrive `
|
|
-Name "VEEAMSRC" `
|
|
-PSProvider FileSystem `
|
|
-Root $NetworkSource `
|
|
-Credential $Credential `
|
|
-ErrorAction Stop | Out-Null
|
|
|
|
|
|
|
|
$script:VeeamSource = $NetworkSource
|
|
|
|
|
|
|
|
Write-Host ""
|
|
|
|
Write-Host "Netzwerkquelle verbunden:"
|
|
|
|
Write-Host $VeeamSource
|
|
|
|
}
|
|
|
|
|
|
default
|
|
{
|
|
|
|
Write-Host "Ungültige Auswahl"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$script:VeeamInstaller =
|
|
"$VeeamSource\Setup\Silent\Veeam.Silent.Install.exe"
|
|
|
|
|
|
|
|
$script:AnswerFileSource =
|
|
"$VeeamSource\Setup\Silent\AnswerFiles\VBR\VbrAnswerFile_install.xml"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function Test-VeeamSource {
|
|
|
|
|
|
Write-Log "Prüfe Installationsquelle"
|
|
|
|
|
|
if(!(Test-Path $VeeamInstaller))
|
|
{
|
|
|
|
Write-Log "FEHLER: Installer nicht gefunden"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
if(!(Test-Path $AnswerFileSource))
|
|
{
|
|
|
|
Write-Log "FEHLER: Antwortdatei nicht gefunden"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
Write-Log "Installationsquelle OK"
|
|
|
|
|
|
}
|
|
############################################################
|
|
# LIZENZ
|
|
############################################################
|
|
|
|
|
|
function Copy-VeeamLicense {
|
|
|
|
|
|
Write-Log "Prüfe Lizenzdatei"
|
|
|
|
|
|
$Source = "$VeeamSource\License\veeam.lic"
|
|
|
|
|
|
|
|
if(Test-Path $Source)
|
|
{
|
|
|
|
Copy-Item `
|
|
-Path $Source `
|
|
-Destination $LicenseTarget `
|
|
-Force `
|
|
-ErrorAction Stop
|
|
|
|
|
|
$script:UseLicenseFile = $true
|
|
|
|
|
|
Write-Log "Lizenzdatei kopiert: $LicenseTarget"
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
$script:UseLicenseFile = $false
|
|
|
|
|
|
Write-Log "Keine Lizenzdatei gefunden"
|
|
|
|
Write-Log "Installation als Community Edition"
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
############################################################
|
|
# ANTWORTDATEI
|
|
############################################################
|
|
|
|
|
|
function Prepare-AnswerFile {
|
|
|
|
|
|
Write-Log "Kopiere Antwortdatei"
|
|
|
|
|
|
|
|
Copy-Item `
|
|
-Path $AnswerFileSource `
|
|
-Destination $AnswerFile `
|
|
-Force `
|
|
-ErrorAction Stop
|
|
|
|
|
|
|
|
if(!(Test-Path $AnswerFile))
|
|
{
|
|
|
|
Write-Log "FEHLER: Antwortdatei nicht vorhanden"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
# Blockierung durch Windows entfernen
|
|
#
|
|
|
|
Unblock-File `
|
|
-Path $AnswerFile `
|
|
-ErrorAction SilentlyContinue
|
|
|
|
|
|
|
|
#
|
|
# Attribute entfernen
|
|
#
|
|
|
|
attrib -R $AnswerFile
|
|
|
|
attrib -S $AnswerFile
|
|
|
|
attrib -H $AnswerFile
|
|
|
|
|
|
|
|
#
|
|
# Rechte setzen
|
|
#
|
|
|
|
icacls `
|
|
$AnswerFile `
|
|
/grant Administrators:F `
|
|
/grant SYSTEM:F `
|
|
| Out-Null
|
|
|
|
|
|
|
|
Write-Log "Antwortdatei vorbereitet"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
############################################################
|
|
# XML ÄNDERN
|
|
############################################################
|
|
|
|
|
|
function Update-AnswerFile {
|
|
|
|
|
|
Write-Log "Bearbeite Antwortdatei"
|
|
|
|
|
|
|
|
try
|
|
{
|
|
|
|
[xml]$XML = Get-Content `
|
|
-Path $AnswerFile `
|
|
-Encoding UTF8
|
|
|
|
}
|
|
catch
|
|
{
|
|
|
|
Write-Log "XML Fehler: $($_.Exception.Message)"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach($Property in $XML.unattendedInstallationConfiguration.properties.property)
|
|
{
|
|
|
|
|
|
switch($Property.name)
|
|
{
|
|
|
|
|
|
"ACCEPT_EULA"
|
|
{
|
|
$Property.value = "1"
|
|
}
|
|
|
|
|
|
|
|
"ACCEPT_LICENSING_POLICY"
|
|
{
|
|
$Property.value = "1"
|
|
}
|
|
|
|
|
|
|
|
"ACCEPT_THIRDPARTY_LICENSES"
|
|
{
|
|
$Property.value = "1"
|
|
}
|
|
|
|
|
|
|
|
"ACCEPT_REQUIRED_SOFTWARE"
|
|
{
|
|
$Property.value = "1"
|
|
}
|
|
|
|
|
|
|
|
"VBR_LICENSE_FILE"
|
|
{
|
|
|
|
if($UseLicenseFile)
|
|
{
|
|
|
|
$Property.value = $LicenseTarget
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
$Property.value = "0"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
"VBR_SQLSERVER_INSTALL"
|
|
{
|
|
$Property.value = "0"
|
|
}
|
|
|
|
|
|
|
|
"VBR_SQLSERVER_ENGINE"
|
|
{
|
|
$Property.value = "0"
|
|
}
|
|
|
|
|
|
|
|
"VBR_SQLSERVER_SERVER"
|
|
{
|
|
$Property.value = $SQLConnection
|
|
}
|
|
|
|
|
|
|
|
"VBR_SQLSERVER_DATABASE"
|
|
{
|
|
$Property.value = $DatabaseName
|
|
}
|
|
|
|
|
|
|
|
"VBR_SQLSERVER_AUTHENTICATION"
|
|
{
|
|
$Property.value = "$SQLAuthentication"
|
|
}
|
|
|
|
|
|
|
|
"VBR_ENTRAID_DATABASE_INSTALL"
|
|
{
|
|
$Property.value = "0"
|
|
}
|
|
|
|
|
|
|
|
"INSTALLDIR"
|
|
{
|
|
$Property.value = $InstallPath
|
|
}
|
|
|
|
|
|
|
|
"VM_CATALOGPATH"
|
|
{
|
|
$Property.value = $CatalogPath
|
|
}
|
|
|
|
|
|
|
|
"VBR_IRCACHE"
|
|
{
|
|
$Property.value = $IRCachePath
|
|
}
|
|
|
|
|
|
|
|
"VBRC_SERVICE_PORT"
|
|
{
|
|
$Property.value = "$GuestCatalogPort"
|
|
}
|
|
|
|
|
|
|
|
"VBR_SERVICE_PORT"
|
|
{
|
|
$Property.value = "$VeeamServicePort"
|
|
}
|
|
|
|
|
|
|
|
"VBR_SECURE_CONNECTIONS_PORT"
|
|
{
|
|
$Property.value = "$SecureConnectionPort"
|
|
}
|
|
|
|
|
|
|
|
"VBR_RESTSERVICE_PORT"
|
|
{
|
|
$Property.value = "$RestServicePort"
|
|
}
|
|
|
|
|
|
|
|
"REBOOT_IF_REQUIRED"
|
|
{
|
|
$Property.value = "$RebootRequired"
|
|
}
|
|
|
|
|
|
|
|
default
|
|
{
|
|
|
|
if($Plugins.ContainsKey($Property.name))
|
|
{
|
|
|
|
$Property.value =
|
|
"$($Plugins[$Property.name])"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
# XML speichern
|
|
#
|
|
|
|
try
|
|
{
|
|
|
|
attrib -R $AnswerFile
|
|
|
|
|
|
$XML.Save($AnswerFile)
|
|
|
|
|
|
|
|
Write-Log "Antwortdatei gespeichert"
|
|
|
|
|
|
}
|
|
catch
|
|
{
|
|
|
|
Write-Log `
|
|
"FEHLER beim Speichern XML: $($_.Exception.Message)"
|
|
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
############################################################
|
|
# INSTALLATIONSPFADE
|
|
############################################################
|
|
|
|
|
|
function Test-RequiredPaths {
|
|
|
|
|
|
Write-Log "Prüfe Installationspfade"
|
|
|
|
|
|
|
|
foreach($Path in @(
|
|
$InstallPath,
|
|
$CatalogPath,
|
|
$IRCachePath
|
|
))
|
|
{
|
|
|
|
|
|
if(!(Test-Path $Path))
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
New-Item `
|
|
-Path $Path `
|
|
-ItemType Directory `
|
|
-Force `
|
|
-ErrorAction Stop | Out-Null
|
|
|
|
|
|
Write-Log "Pfad erstellt: $Path"
|
|
|
|
|
|
}
|
|
catch
|
|
{
|
|
|
|
Write-Log `
|
|
"FEHLER Pfad $Path : $($_.Exception.Message)"
|
|
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
Write-Log "Pfad vorhanden: $Path"
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
############################################################
|
|
# VEEAM INSTALLATION
|
|
############################################################
|
|
|
|
|
|
function Install-Veeam {
|
|
|
|
|
|
Write-Log "Starte Veeam Installation"
|
|
|
|
|
|
|
|
$Arguments = @(
|
|
"/AnswerFile"
|
|
"`"$AnswerFile`""
|
|
"/SkipNetworkLogonErrors"
|
|
)
|
|
|
|
|
|
|
|
try
|
|
{
|
|
|
|
$Process = Start-Process `
|
|
-FilePath $VeeamInstaller `
|
|
-ArgumentList $Arguments `
|
|
-Wait `
|
|
-PassThru `
|
|
-ErrorAction Stop
|
|
|
|
|
|
}
|
|
catch
|
|
{
|
|
|
|
Write-Log `
|
|
"FEHLER beim Start des Installers: $($_.Exception.Message)"
|
|
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
Write-Log `
|
|
"Installer ExitCode: $($Process.ExitCode)"
|
|
|
|
|
|
|
|
switch($Process.ExitCode)
|
|
{
|
|
|
|
|
|
0
|
|
{
|
|
|
|
Write-Log "Installation erfolgreich"
|
|
|
|
}
|
|
|
|
|
|
|
|
3010
|
|
{
|
|
|
|
Write-Log `
|
|
"Installation erfolgreich - Neustart erforderlich"
|
|
|
|
}
|
|
|
|
|
|
|
|
1603
|
|
{
|
|
|
|
Write-Log `
|
|
"FEHLER 1603 - MSI Installationsfehler"
|
|
|
|
|
|
exit 1603
|
|
|
|
}
|
|
|
|
|
|
|
|
default
|
|
{
|
|
|
|
Write-Log `
|
|
"Installation fehlgeschlagen"
|
|
|
|
|
|
exit $Process.ExitCode
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
############################################################
|
|
# INSTALLATIONSERGEBNIS
|
|
############################################################
|
|
|
|
|
|
function Show-Result {
|
|
|
|
|
|
Write-Host ""
|
|
|
|
Write-Host "================================="
|
|
|
|
Write-Host "Veeam Installation abgeschlossen"
|
|
|
|
Write-Host "================================="
|
|
|
|
Write-Host ""
|
|
|
|
Write-Host "Logdatei:"
|
|
|
|
Write-Host "$LogDir\Install.log"
|
|
|
|
Write-Host ""
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
############################################################
|
|
# MAIN
|
|
############################################################
|
|
|
|
|
|
function Main {
|
|
|
|
|
|
#
|
|
# Alte Daten entfernen
|
|
#
|
|
|
|
Remove-OldInstallFiles
|
|
|
|
|
|
|
|
#
|
|
# Arbeitsverzeichnis erstellen
|
|
#
|
|
|
|
Initialize-Directories
|
|
|
|
|
|
|
|
Write-Log `
|
|
"==== Veeam Backup & Replication v13 Installation gestartet ===="
|
|
|
|
|
|
|
|
#
|
|
# Quelle wählen
|
|
#
|
|
|
|
Select-VeeamSource
|
|
|
|
|
|
|
|
#
|
|
# Quelle prüfen
|
|
#
|
|
|
|
Test-VeeamSource
|
|
|
|
|
|
|
|
#
|
|
# Lizenz
|
|
#
|
|
|
|
Copy-VeeamLicense
|
|
|
|
|
|
|
|
#
|
|
# Antwortdatei
|
|
#
|
|
|
|
Prepare-AnswerFile
|
|
|
|
|
|
|
|
Update-AnswerFile
|
|
|
|
|
|
|
|
#
|
|
# Zielpfade
|
|
#
|
|
|
|
Test-RequiredPaths
|
|
|
|
|
|
|
|
#
|
|
# Installation
|
|
#
|
|
|
|
Install-Veeam
|
|
|
|
|
|
|
|
Write-Log `
|
|
"==== Veeam Installation beendet ===="
|
|
|
|
|
|
|
|
Show-Result
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
############################################################
|
|
# START
|
|
############################################################
|
|
|
|
Main
|
|
|
|
|
|
|