Veeam Availability Suite Unattended Install

Um mein Lab bei Bedarf wieder schnell aufzubauen habe ich mir vorgenommen alle Installationen, soweit möglich, zu automatisieren. Da nun auch wieder ein Veeam Backup & Replication 9.5 Server mit Veeam Enterprise Manager zu meinem Lab gehören soll, war mein erstes PowerShell Projekt der Veeam Availability Suite Unattended Install.

Natürlich habe ich mich als erstes umgesehen, ob sich nicht bereits jemand Anderes die Arbeit gemacht hat. Und tatsächlich, das Projekt von Timothy Dewin ist sogar in dem Veeam PowerShell GitHub Repository zur Verfügung gestellt (95_simple_auto_install_all.ps1). Dieses Skript sieht schon mehr als ordentlich aus, ich konnte es aber natürlich dennoch nicht lassen es noch etwas zu überarbeiten.

Veeam Availability Suite Unattended Install - Console

Veeam Availability Suite Unattended Install

Zusätzlich zur reinen Installation der Veeam Availability Suite 9.5 hab ich mir auch angesehen wie man einige der grundlegenden Konfigurationen automatisieren könnte, z.B. VMware vCenter oder NetApp ONTAP Filer in Veeam Backup & Replication 9.5 aufnehmen. Daher ist der Artikel auch in zwei Teilabschnitte gegliedert.

Abschnitte:

Veeam Availability Suite Unattended Install im Detail

Wie bereits erwähnt habe ich mir als Basis das Skript von Timothy Dewin genommen und dieses etwas verfeinert. Wichtig war für mich unter anderem die Kontrolle der MSI Logs auf eine erfolgreiche Installation. Dazu suche ich ganz simple in dem Log nach dem String für eine fehlerfreie Installation „Installation success or error status: 0„.

Beispiel:

if (Select-String -path "$logdir\02_Shared.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

Die Anlage des lokalen Users für die Veeam Prozesse und die SQL Verbindung habe ich anders als beim dem originalen Skript mit dem in PowerShell 5.1 neu eingeführten Cmdlet New-LocalUser erledigt. Nachteil ist natürlich, dass man diese PowerShell Version installiert haben muss.

Alle notwendigen MSI Parameter für die einzelnen Veeam Komponenten können dem Veeam Unattended Installation Guide entnommen werden.

Unattended Install Skript

Um das Veeam Availability Suite Unattended Install Skript erfolgreich auszuführen, müssen ein paar Voranforderungen erfüllt werden:

  • PowerShell 5.1 ist installiert und neu gestartet
  • .Net 4.5.2 ist installiert und neu gestartet
  • Veeam Availability Suite 9.5 Update 2 ISO ist eingelegt
  • Administrator Rechte sind vorhanden

Für die beiden zusätzlichen Software Pakete habe ich die Installationsroutinen auch in das Skript eingefügt aber auskommentiert. Um PowerShell 5.1 zu installieren muss das Windows Management Framework 5.1 heruntergeladen werden, .Net 4.5.2 ist auf dem Veeam Availability Suite 9.5 Update 2 ISO zu finden.

# Requires PowerShell 5.1
# Requires .Net 4.5.2 and Reboot

#region: Variables
$source = "F:"
$licensefile = "C:\_install\veeam_availability_suite_trial_32_0.lic"
$username = "svc_veeam"
$fulluser = $env:COMPUTERNAME+ "\" + $username
$password = "Passw0rd!"
$CatalogPath = "D:\VbrCatalog"
$vPowerPath = "D:\vPowerNfs"
#endregion

#region: logdir
$logdir = "C:\logdir"
$trash = New-Item -ItemType Directory -path $logdir  -ErrorAction SilentlyContinue
#endregion

### Optional .Net 4.5.2
<#
Write-Host "    Installing .Net 4.5.2 ..." -ForegroundColor Yellow
$Arguments = "/quiet /norestart"
Start-Process "$source\Redistr\NDP452-KB2901907-x86-x64-AllOS-ENU.exe" -ArgumentList $Arguments -Wait -NoNewWindow
Restart-Computer -Confirm:$true
#>

### Optional PowerShell 5.1
<#
Write-Host "    Installing PowerShell 5.1 ..." -ForegroundColor Yellow
$Arguments = "C:\_install\Win8.1AndW2K12R2-KB3191564-x64.msu /quiet /norestart"
Start-Process "wusa.exe" -ArgumentList $Arguments -Wait -NoNewWindow
Restart-Computer -Confirm:$true
#>

#region: create local admin
Write-Host "Creating local user '$fulluser' with password '$password' ..." -ForegroundColor Yellow
$trash = New-LocalUser -Name $username -Password ($password | ConvertTo-SecureString -AsPlainText -Force) -Description "Service Account for Veeam" -AccountNeverExpires -ErrorAction Stop
Add-LocalGroupMember -Group "Administrators" -Member $username -ErrorAction Stop
#endregion

#region: Installation
#  Info: https://www.veeam.com/unattended_installation_ds.pdf

## Global Prerequirements
Write-Host "Installing Global Prerequirements ..." -ForegroundColor Yellow
### 2012 System CLR Types
Write-Host "    Installing 2012 System CLR Types ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Redistr\x64\SQLSysClrTypes.msi"
    "/qn"
    "/norestart"
    "/L*v"
    "$logdir\01_CLR.txt"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\01_CLR.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### 2012 Shared management objects
Write-Host "    Installing 2012 Shared management objects ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Redistr\x64\SharedManagementObjects.msi"
    "/qn"
    "/norestart"
    "/L*v"
    "$logdir\02_Shared.txt"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\02_Shared.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### SQL Express
### Info: https://msdn.microsoft.com/en-us/library/ms144259.aspx
Write-Host "    Installing SQL Express ..." -ForegroundColor Yellow
$Arguments = "/HIDECONSOLE /Q /IACCEPTSQLSERVERLICENSETERMS /ACTION=install /FEATURES=SQLEngine,SNAC_SDK /INSTANCENAME=VEEAMSQL2012 /SQLSVCACCOUNT=`"NT AUTHORITY\SYSTEM`" /SQLSYSADMINACCOUNTS=`"$fulluser`" `"Builtin\Administrators`" /TCPENABLED=1 /NPENABLED=1 /UpdateEnabled=0"
Start-Process "$source\Redistr\x64\SQLEXPR_x64_ENU.exe" -ArgumentList $Arguments -Wait -NoNewWindow

## Veeam Backup & Replication
Write-Host "Installing Veeam Backup & Replication ..." -ForegroundColor Yellow
### Backup Catalog
Write-Host "    Installing Backup Catalog ..." -ForegroundColor Yellow
$trash = New-Item -ItemType Directory -path $CatalogPath -ErrorAction SilentlyContinue
$MSIArguments = @(
    "/i"
    "$source\Catalog\VeeamBackupCatalog64.msi"
    "/qn"
    "/L*v"
    "$logdir\04_Catalog.txt"
    "VM_CATALOGPATH=$CatalogPath"
    "VBRC_SERVICE_USER=$fulluser"
    "VBRC_SERVICE_PASSWORD=$password"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\04_Catalog.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### Backup Server
Write-Host "    Installing Backup Server ..." -ForegroundColor Yellow
$trash = New-Item -ItemType Directory -path $vPowerPath -ErrorAction SilentlyContinue
$MSIArguments = @(
    "/i"
    "$source\Backup\Server.x64.msi"
    "/qn"
    "/L*v"
    "$logdir\05_Backup.txt"
    "ACCEPTEULA=YES"
    "VBR_LICENSE_FILE=$licensefile"
    "VBR_SERVICE_USER=$fulluser"
    "VBR_SERVICE_PASSWORD=$password"
    "PF_AD_NFSDATASTORE=$vPowerPath"
    "VBR_SQLSERVER_SERVER=$env:COMPUTERNAME\VEEAMSQL2012"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\05_Backup.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### Backup Console
Write-Host "    Installing Backup Console ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Backup\Shell.x64.msi"
    "/qn"
    "/L*v"
    "$logdir\06_Console.txt"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\06_Console.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### Explorers
Write-Host "    Installing Explorer For ActiveDirectory ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Explorers\VeeamExplorerForActiveDirectory.msi"
    "/qn"
    "/L*v"
    "$logdir\07_ExplorerForActiveDirectory.txt"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\07_ExplorerForActiveDirectory.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

Write-Host "    Installing Explorer For Exchange ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Explorers\VeeamExplorerForExchange.msi"
    "/qn"
    "/L*v"
    "$logdir\08_VeeamExplorerForExchange.txt"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\08_VeeamExplorerForExchange.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

Write-Host "    Installing Explorer For SQL ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Explorers\VeeamExplorerForSQL.msi"
    "/qn"
    "/L*v"
    "$logdir\09_VeeamExplorerForSQL.txt"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\09_VeeamExplorerForSQL.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

Write-Host "    Installing Explorer For Oracle ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Explorers\VeeamExplorerForOracle.msi"
    "/qn"
    "/L*v"
    "$logdir\10_VeeamExplorerForOracle.txt"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\10_VeeamExplorerForOracle.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

Write-Host "    Installing Explorer For SharePoint ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\Explorers\VeeamExplorerForSharePoint.msi"
    "/qn"
    "/L*v"
    "$logdir\11_VeeamExplorerForSharePoint.txt"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\11_VeeamExplorerForSharePoint.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

## Enterprise Manager
Write-Host "Installing Enterprise Manager ..." -ForegroundColor Yellow
### Enterprise Manager Prereqirements
Write-Host "    Installing Enterprise Manager Prereqirements ..." -ForegroundColor Yellow
$trash = Install-WindowsFeature Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Windows-Auth -Restart:$false -WarningAction SilentlyContinue
$trash = Install-WindowsFeature Web-Http-Logging,Web-Stat-Compression,Web-Filtering,Web-Net-Ext45,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter,Web-Mgmt-Console -Restart:$false  -WarningAction SilentlyContinue

$MSIArguments = @(
    "/i"
    "$source\Redistr\x64\rewrite_amd64.msi"
    "/qn"
    "/norestart"
    "/L*v"
    "$logdir\12_Rewrite.txt"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\12_Rewrite.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### Enterprise Manager Web
Write-Host "    Installing Enterprise Manager Web ..." -ForegroundColor Yellow
$MSIArguments = @(
    "/i"
    "$source\EnterpriseManager\BackupWeb_x64.msi"
    "/qn"
    "/L*v"
    "$logdir\13_EntWeb.txt"
    "ACCEPTEULA=YES"
    "VBREM_LICENSE_FILE=$licensefile"
    "VBREM_SERVICE_USER=$fulluser"
    "VBREM_SERVICE_PASSWORD=$password"
    "VBREM_SQLSERVER_SERVER=$env:COMPUTERNAME\VEEAMSQL2012"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

if (Select-String -path "$logdir\13_EntWeb.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### Enterprise Manager Cloud Portal
Write-Host "    Installing Enterprise Manager Cloud Portal ..." -ForegroundColor Yellow
<#
$MSIArguments = @(
    "/i"
    "$source\Cloud Portal\BackupCloudPortal_x64.msi"
    "/L*v"
    "$logdir\14_EntCloudPortal.txt"
    "/qn"
    "ACCEPTEULA=YES"
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow
#>
Start-Process "msiexec.exe" -ArgumentList "/i `"$source\Cloud Portal\BackupCloudPortal_x64.msi`" /l*v $logdir\14_EntCloudPortal.txt /qn ACCEPTEULA=`"YES`"" -Wait -NoNewWindow

if (Select-String -path "$logdir\14_EntCloudPortal.txt" -pattern "Installation success or error status: 0.") {
    Write-Host "    Setup OK" -ForegroundColor Green
    }
    else {
        throw "Setup Failed"
        }

### Update 2
Write-Host "Installing Update 2 ..." -ForegroundColor Yellow
$Arguments = "/silent /noreboot /log $logdir\15_update.txt VBR_AUTO_UPGRADE=1"
Start-Process "$source\Updates\veeam_backup_9.5.0.1038.update2_setup.exe" -ArgumentList $Arguments -Wait -NoNewWindow
#endregion

Das Skript ist auch GitHub Gist zur Verfügung gestellt.

Vorsicht:

Der letzte Schritt in dem Veeam Availability Suite Unattended Install PowerShell Skript ist die Installation des Update 2. Dieses befindet sich erst seit kurzem mit auf dem ISO!

Weitere Konfigurationen

Neben dem reinen Veeam Availability Suite Unattended Install sind zusätzlich grundlegende Konfigurationen an der frischen Installation denkbar.

Zusätzliche Konfigurationen:

  • vCenter hinzufügen
  • NetApp Filer hinzufügen
  • Backup Server in Enterprise Manager aufnehmen

vCenter zu Veeam Backup Server hinzufügen

Für diese Konfiguration muss das mit der Konsole zusammen installierte Veeam PowerShell PSSnapIn genutzt werden, und zwar konkret das Add-VBRvCenter Cmdlet. Wie der Veeam PowerShell Reference zu entnehmen ist, kann hierfür ein User mit Passwort mitgegeben werden oder auf bestehende Credentials zugegriffen werden. Ich mache in meinem Beispiel ersteres.

if (Get-PSSnapin -Registered -Name VeeamPSSnapIn -ErrorAction SilentlyContinue) {
    Add-PSSnapin -Name VeeamPSSnapIn
    }

Disconnect-VBRServer -ErrorAction SilentlyContinue
Connect-VBRServer -Server Veeam-01.lab.local

if (Get-VBRServer) {
    Add-VBRvCenter -Name "192.168.3.101" -Description "Lab vCenter" -User "[email protected]" -Password "Passw0rd!" -Verbose
    }

NetApp Filer zu Veeam Backup Server hinzufügen

Für das Add-NetAppHost Cmdlet gilt das gleiche wie im vorherigen Schritt mit dem vCenter, Details sind der Veeam PowerShell Reference zu entnehmen.

if (Get-PSSnapin -Registered -Name VeeamPSSnapIn -ErrorAction SilentlyContinue) {
    Add-PSSnapin -Name VeeamPSSnapIn
    }

Disconnect-VBRServer -ErrorAction SilentlyContinue
Connect-VBRServer -Server Veeam-01.lab.local

if (Get-VBRServer) {
    Add-NetAppHost -Name "192.168.3.103" -Description "Lab NetApp" -UserName "admin" -Password "Anfang!!11"
    }

Veeam Backup Server zu Enterprise Manager hinzufügen

Für diese Konfiguration muss auf die Veeam Backup Enterprise Manager RESTful API zugegriffen werden, daher ist das Skript leider auch entsprechend komplexer.

Es sing vier REST Calls notwendig:

  1. Authentifizieren
  2. Server hinzufügen
  3. Server ID abrufen (optional)
  4. Server Collection (optional)

Die Collection ist optional, da der „default schedule“ für die Collection ohnehin alle 15 Minuten läuft.

[String] $Server = "192.168.3.100"
[Boolean] $HTTPS = $True
[String] $Port = "9398"
[String] $Authentication = "<dummy>"

#region: Workaround for SelfSigned Cert
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#endregion

#region: Switch Http/s
if ($HTTPS -eq $True) {$Proto = "https"} else {$Proto = "http"}
#endregion

#region: POST - Authorization
[String] $URL = $Proto + "://" + $Server + ":" + $Port + "/api/sessionMngr/?v=v1_2"
Write-Verbose "Authorization Url: $URL"
$Auth = @{uri = $URL;
                   Method = 'POST';
                   Headers = @{Authorization = 'Basic ' + $Authentication;
           }
   }
try {$AuthXML = Invoke-WebRequest @Auth -ErrorAction Stop} catch {Write-Error "`nERROR: Authorization Failed!";Exit 1}
#endregion

#region: POST - Add BR Server
[String] $URL = $Proto + "://" + $Server + ":" + $Port + "/api/backupServers?action=create"
Write-Verbose "Add BR Server Url: $URL"
$BRServer = @{uri = $URL;
                   Method = 'POST';
				   Headers = @{'X-RestSvcSessionId' = $AuthXML.Headers['X-RestSvcSessionId'];
                                'Content-Type' = 'application/xml'}
                   Body = '
                   <BackupServerSpec xmlns="http://www.veeam.com/ent/v1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                     <Description>Veeam Lab Server</Description>
                     <DnsNameOrIpAddress>192.168.3.100</DnsNameOrIpAddress>
                     <Port>9392</Port>
                     <Username>Veeam-01\svc_veeam</Username>
                     <Password>Passw0rd!</Password>
                    </BackupServerSpec>
                    '
           } 
	
try {$BRServerXML = Invoke-RestMethod @BRServer -ErrorAction Stop} catch {Write-Error "`nERROR: Add BR Server Failed!";Exit 1}
#endregion

#region: GET - Get BR Server
[String] $URL = $Proto + "://" + $Server + ":" + $Port + "/api/backupServers"
Write-Verbose "Get BR Server Url: $URL"
$BRServer = @{uri = $URL;
                   Method = 'GET';
				   Headers = @{'X-RestSvcSessionId' = $AuthXML.Headers['X-RestSvcSessionId']}
           } 
	
try {$BRServerXML = Invoke-RestMethod @BRServer -ErrorAction Stop} catch {Write-Error "`nERROR: Get BR Server Failed!";Exit 1}

#endregion

#region: POST - Collect BR Server
[String] $URL = $BRServerXML.EntityReferences.Ref.Href + "?action=collect"
Write-Verbose "Collect BR Server Url: $URL"
$BRServer = @{uri = $URL;
                   Method = 'POST';
				   Headers = @{'X-RestSvcSessionId' = $AuthXML.Headers['X-RestSvcSessionId']}
           } 
	
try {$BRServerXML = Invoke-RestMethod @BRServer -ErrorAction Stop} catch {Write-Error "`nERROR: Collect BR Server Failed!";Exit 1}
#endregion

 

Leave a Reply