Hyper-V GetSANPath Funktion

Eine kleine Funktion „GetSANPath“, um die Cluster Shared Volumes inkl. ein paar Infos in einem Grid View auszugeben und auszuwählen.

Die PowerShell Funktion GetSANPath liest alle gemounteten Cluster Shared Volumes aus und holt sich Informationen zu Größe und freiem sowie genutztem Speicherplatz. Die Informationen werden dann ein wenig sortiert und in einem Grid View ausgegeben. Das ausgewählte CSV wird anschließend in eine Variable geschrieben, auf die gewünschten Infos „Name“ und „Pfad“ gekürzt und zurückgegeben.

Den größten bzw. wichtigsten Teil des Scriptes habe ich im Script Center des Technets gefunden: https://gallery.technet.microsoft.com/scriptcenter/Monitor-Cluster-Shared-21de7554

function GetSANPath {
    $Output = @()
    $csvs = Get-ClusterSharedVolume
    foreach ( $csv in $csvs ) {
        $csvinfos = $csv | select -Property Name -ExpandProperty SharedVolumeInfo
        foreach ( $csvinfo in $csvinfos ) {
            $temp_csv = New-Object PSObject -Property @{
                Name = $csv.Name
                Size = $([math]::round((($csvinfo.Partition.Size) / 1GB), 2))
                FreeSpace = $([math]::round((($csvinfo.Partition.FreeSpace) / 1GB), 2))
                UsedSpace = $([math]::round((($csvinfo.Partition.UsedSpace) / 1GB), 2))
                PercentFree = $csvinfo.Partition.PercentFree
                Path = $csvinfo.FriendlyVolumeName
            }  
 
            $Output += $temp_csv
        }
    }
do {
    $SAN = $Output | Select-Object Name, @{l="Größe in GB"; e={$_.Size}}, @{l="Freier Speicher in GB"; e={$_.FreeSpace}}, @{l="Benutzter Speicher in GB"; e={$_.UsedSpace}}, @{l="Freier Speicher in %"; e={$_.PercentFree}}, @{l="Pfad"; e={$_.Path}} | Out-GridView -PassThru
} until ($SAN)
 
$SAN = @{
            Name = $SAN.Name
            Path = $SAN.Pfad
        }
 
return $SAN
}

Auf Active Directory Start in Hyper-V VM warten

Den vollständigen Start des Active Directory in einer Hyper-V VM abwarten.

Das gestern vorgestellt Script „RebootAndWaitForServer“ wartet nur „stumpf“ bis die Hyper-V VM gebootet ist und der Prozess „winlogon.exe“ sowie der Dienst „LSM“ läuft. Stellt man jetzt eine Umgebung auf der grünen Wiese bzw. einen PoC oder eine Demoumgebung bereit, benötigt man unter Umständen einen Domänen Controller. Ein DC sollte nicht nur automatisch ausgerollt, sondern auch noch entsprechend konfiguriert werden. Die Konfiguration ist allerdings, logischerweise, erst möglich wenn die Active Directory Dienste gestartet und betriebsbereit sind. Auch hier gab es auf GitHub (WaitFor-ActiveDirectory) bereits eine Funktion, die in verschiedenen Tests nicht zuverlässig lief. In prduktiven Umgebungen sollte es diese Problem natürlich gar nicht erst, da immer mindestens zwei Domain Controller betrieben werden sollten, von denen einer immer erreichbar ist.

Das folgende Script liest die Uptime der Hyper-V VM aus, zieht diese vom aktuellen Datum ab und durchsucht dann die Ereignisanzeige „Active Directory Web Services“ in der VM auf die Instanz-Id „1073743024“.

# WaitForAD
Beispiel für die Variablen:
    [string]$VMName = "SERVER-VM01"
    [System.Management.Automation.PSCredential] $tempCred = new-object -typename System.Management.Automation.PSCredential ("Domain\Admin", (ConvertTo-SecureString P@ssw0rd! -AsPlainText -Force))
 
Oder ggfs. die Variablen abfragen:
    $VMName = Read-Host "Bitte den Namen des virtuellen Computers eingeben"
    $tempCred = Get-Credential
#>
 
function WaitForAD {
    param (
        [Parameter(Mandatory=$true)]
        [String]
        $VMName,
 
        [Parameter(Mandatory=$true)]
        [System.Management.Automation.PSCredential]
        $Credentials
 
    )
    $VM = Get-VM -Name $VMName
    $Uptime = $VM.Uptime.TotalSeconds
    $Date = $(Get-Date).AddSeconds(-($Uptime))
    Write-Host "[$($VMName)]:: Auf Active Directory warten" -ForegroundColor Yellow -NoNewline
    Invoke-Command -VMName $VMName -Credential $Credentials -ArgumentList $Date -ScriptBlock {
        param($Date)
        do {
            do {
                Write-Host "." -ForegroundColor Yellow -NoNewline
                Start-Sleep -Seconds 5
                $AD = get-service ADWS, DNS, KDC, NETLOGON, NTDS
            } until ($AD[0].Status -eq "running" -and $AD[1].Status -eq "running" -and $AD[2].Status -eq "running" -and $AD[3].Status -eq "running" -and $AD[4].Status -eq "running")
            Write-Host "." -ForegroundColor Yellow -NoNewline
            Start-Sleep -Seconds 5
            $Event = Get-EventLog -LogName "Active Directory Web Services" -Source ADWS -After $Date -InstanceId 1073743024 -Newest 1
        } until ($Event.Message -match "Die angegebene Verzeichnisinstanz wird nun von Active Directory-Webdiensten bedient" -or $Event.Message -match "Active Directory Web Services is now servicing the specified directory instance")
    }
    Write-Host " -> Ok!" -ForegroundColor Yellow
}
 
[string]$VMName = "SERVER-VM01"
[System.Management.Automation.PSCredential] $tempCred = new-object -typename System.Management.Automation.PSCredential ("Domain\Administrator", (ConvertTo-SecureString P@ssw0rd! -AsPlainText -Force))
 
WaitForAD $VMName $tempCred

Link zum Download: WaitForAD

Aint nobody got time for dat
Aint nobody got time for dat

Warten bis Hyper-V VM neu gestartet ist

Neustart einer Hyper-V VM initiieren und abwarten bis das Windows Serverbetriebssystem geladen ist.

In einem größeren Projekt wird mittels eines leicht angepassten Image Factory Script per Task wöchentlich eine mit Updates versogte Windows Server 2016 VHDX erstellt und später in einem Deployment Prozess per PowerShell weiterverarbeitet. Beim Rollout diverse VMs wird natürlich auch diverses an Software bzw. Applikationen in den VMs benötigt. Die Installation der Applikationen benötigen hin und wieder leider auch Reboots. Gewisse Schritte müssen dann auch noch auf andere Applikation oder Dienste warten. Ebenfalls passiert es ab und zu, dass ein Reboot länger verzögert bis z.B. Dienste beendet sind. Der Bootvorgang kann durchaus auch schon abgeschlossen sein und direkt erneut booten, da noch weitere Updates oder Features konfiguriert werden müssen.

Für dieses Problem gab es bereits z.B. waitForPSDirect oder auch Invoke-CommandWithPSDirect. Bei beiden Scripts kann es passieren, dass die Hyper-V VM bereits per PowerShell Direct angesprochen werden kann, obwohl noch ein weiterer Reboot aussteht. Aus diesem Grund habe ich die beiden Scripte kombiniert und ein wenig erweitert. Im Groben fährt das Script die Hyper-V VM herunter, startet diese neu, überprüft den Status des Taktes (Heartbeat) Get-VMIntegrationService und wartet bis die „winlogon.exe“ und der „Lokaler Sitzungs-Manager (LSM)“ laufen.

Reboot And Wait For Server Ausgabe
Reboot And Wait For Server Ausgabe

Wichtig: Wenn während dem Deployment die Software / Applikation in der Hyper-V VM installiert wird, diese nicht über die Installationsroutinen neu starten. Zum kontrollierten Reboot nur die PowerShell Funktion „RebootAndWaitForServer“ nutzen.

# RebootAndWaitForServer
Beispiel für die Variablen:
    [string]$VMName = "SERVER-VM01"
    [System.Management.Automation.PSCredential] $tempCred = new-object -typename System.Management.Automation.PSCredential ("Domain\Admin", (ConvertTo-SecureString P@ssw0rd! -AsPlainText -Force))
 
Oder ggfs. die Variablen abfragen:
    $VMName = Read-Host "Bitte den Namen des virtuellen Computers eingeben"
    $tempCred = Get-Credential
#>
 
function RebootAndWaitForServer {
    param (
        [Parameter(Mandatory=$true)]
        [String]
        $VMName,
 
        [Parameter(Mandatory=$true)]
        [System.Management.Automation.PSCredential]
        $Credentials
 
    )
    $VM = Get-VM -Name $VMName
    If ($Vm.State -eq "Running") {
        Write-Host "[$($VMName)]:: Fahre Computer herunter" -ForegroundColor Yellow -NoNewline
        Invoke-Command -VMName $VMName -Credential $Credentials -ScriptBlock {
            Stop-Computer -Force -Confirm:$false
        }
        do {
            Write-Host "." -ForegroundColor Yellow -NoNewline
            Sleep -Seconds 5
        } until ($VM.State -eq "Off")
        Write-Host " -> Ok!" -ForegroundColor Yellow
    }
    If ($Vm.State -eq "Off") {
        Write-Host "[$($VMName)]:: Starte Computer neu" -ForegroundColor Yellow -NoNewline
        Start-VM -VM $VM
        do {
            Write-Host "." -ForegroundColor Yellow -NoNewline
            Sleep -Seconds 5
            $VMStatus = Get-VMIntegrationService -VM $VM | ? Id -match "84EAAE65-2F2E-45F5-9BB5-0E857DC8EB47"
        } until($VMStatus.PrimaryStatusDescription.ToUpper() -eq "OK" -and $VMStatus.SecondaryStatusDescription.ToUpper() -eq "OK")
        Write-Host " -> Ok!" -ForegroundColor Yellow
        Write-Host "[$($VMName)]:: Warte auf Winlogon.exe und LSM Dienst" -ForegroundColor Yellow -NoNewline
        Invoke-Command -VMName $VMName -Credential $Credentials -ScriptBlock {
            do {
                Write-Host "." -ForegroundColor Yellow -NoNewline
                Sleep -Seconds 5
                $Process = Get-Process | ? ProcessName -eq "winlogon" -ErrorAction SilentlyContinue
                $LSM = Get-Service LSM -ErrorAction SilentlyContinue
                if ($Process.ProcessName -eq "winlogon" -and $LSM.Status -eq "Running") {
                    $Winlogon = 1
                }
                else {
                    $Winlogon = 0
                }
            } until ($winlogon -eq 1)
        }
    }
    Write-Host " -> Ok!" -ForegroundColor Yellow
}
 
[string]$VMName = "SERVER-VM01"
[System.Management.Automation.PSCredential] $tempCred = new-object -typename System.Management.Automation.PSCredential ("Domain\Administrator", (ConvertTo-SecureString P@ssw0rd! -AsPlainText -Force))
 
RebootAndWaitForServer $VMName $tempCred

Link zum Download: RebootAndWaitForServer

RebootAndWaitForServer
RebootAndWaitForServer