Merge pull request #465 from microsoft/dev

Dev
This commit is contained in:
Jaromir Kaspar 2021-10-11 17:52:34 +02:00 коммит произвёл GitHub
Родитель 9f450dd6e3 961f8f0831
Коммит d6e9c0a451
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 566 добавлений и 24 удалений

Просмотреть файл

@ -536,18 +536,9 @@
#IeePriorityTag needs to be On if you want tag your nonRDMA traffic for QoS. Can be off if you use adapters that pass vSwitch (both SR-IOV and RDMA bypasses vSwitch)
Invoke-Command -ComputerName $servers -ScriptBlock {Set-VMNetworkAdapter -ManagementOS -Name "SMB*" -IeeePriorityTag on}
#validate flow control setting
Invoke-Command -ComputerName $servers -ScriptBlock { Get-NetQosFlowControl} | Sort-Object -Property PSComputername | Format-Table PSComputerName,Priority,Enabled -GroupBy PSComputerName
#Validate DCBX setting
Invoke-Command -ComputerName $servers -ScriptBlock {Get-NetQosDcbxSetting} | Sort-Object PSComputerName | Format-Table Willing,PSComputerName
#Apply policy to the target adapters. The target adapters are adapters connected to vSwitch
Invoke-Command -ComputerName $servers -ScriptBlock {Enable-NetAdapterQos -InterfaceDescription (Get-VMSwitch).NetAdapterInterfaceDescriptions}
#validate policy
Invoke-Command -ComputerName $servers -ScriptBlock {Get-NetAdapterQos | Where-Object enabled -eq true} | Sort-Object PSComputerName
#Create a Traffic class and give SMB Direct 60% of the bandwidth minimum. The name of the class will be "SMB".
#This value needs to match physical switch configuration. Value might vary based on your needs.
#If connected directly (in 2 node configuration) skip this step.

Просмотреть файл

@ -0,0 +1,18 @@
$LabConfig=@{DomainAdminName='LabAdmin'; AdminPassword='LS1setup!' ; <#Prefix = 'WSLab-'#> ; DCEdition='4'; Internet=$true ; TelemetryLevel='Full' ; TelemetryNickname='' ; AdditionalNetworksConfig=@(); VMs=@()}
#2019 cluster
1..4 | ForEach-Object {$LABConfig.VMs += @{ VMName = "S2D$_" ; Configuration = 'S2D' ; ParentVHD = 'Win2019Core_G2.vhdx' ; HDDNumber = 10 ; HDDSize= 10TB ; MemoryStartupBytes= 4GB ; NestedVirt=$True}}
#AzSHCI cluster
1..4 | ForEach-Object {$LABConfig.VMs += @{ VMName = "AzSHCI$_" ; Configuration = 'S2D' ; ParentVHD = 'AzSHCI21H2_G2.vhdx' ; HDDNumber = 10 ; HDDSize= 10TB ; MemoryStartupBytes= 4GB ; NestedVirt=$True}}
#VHDs for in-place
1..4 | ForEach-Object {$VMNames="NewAzSHCI"; $LABConfig.VMs += @{ VMName = "$VMNames$_" ; ParentVHD = 'AzSHCI21H2_G2.vhdx' ; MemoryStartupBytes= 1GB }}
#or without nested virt with small amount of RAM
<#
#2019 cluster
1..4 | ForEach-Object {$LABConfig.VMs += @{ VMName = "S2D$_" ; Configuration = 'S2D' ; ParentVHD = 'Win2019Core_G2.vhdx' ; HDDNumber = 10 ; HDDSize= 10TB ; MemoryStartupBytes= 1GB }}
#AzSHCI cluster
1..4 | ForEach-Object {$LABConfig.VMs += @{ VMName = "AzSHCI$_" ; Configuration = 'S2D' ; ParentVHD = 'AzSHCI21H2_G2.vhdx' ; HDDNumber = 10 ; HDDSize= 10TB ; MemoryStartupBytes= 1GB }}
#VHDs for in-place
1..4 | ForEach-Object {$VMNames="NewAzSHCI"; $LABConfig.VMs += @{ VMName = "$VMNames$_" ; ParentVHD = 'AzSHCI21H2_G2.vhdx' ; MemoryStartupBytes= 1GB }}
#>

Просмотреть файл

@ -0,0 +1,509 @@
#Run all code from DC
#region prereqs - will setup two simplified clusters
#setup 2 clusters
# variables
$Clusters=@()
$Clusters+=@{Nodes=1..4 | Foreach-Object {"S2D$_"} ; Name="S2D-Cluster" ; IP="10.0.0.112" ; vSwitchName="vSwitch"}
$Clusters+=@{Nodes=1..4 | Foreach-Object {"AzSHCI$_"} ; Name="AzSHCI-Cluster" ; IP="10.0.0.113" ; vSwitchName="vSwitch"}
# Install features for management
$WindowsInstallationType=Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\' -Name InstallationType
if ($WindowsInstallationType -eq "Server"){
Install-WindowsFeature -Name RSAT-Clustering,RSAT-Clustering-Mgmt,RSAT-Clustering-PowerShell,RSAT-Hyper-V-Tools
}elseif ($WindowsInstallationType -eq "Server Core"){
Install-WindowsFeature -Name RSAT-Clustering,RSAT-Clustering-PowerShell,RSAT-Hyper-V-Tools
}
# Install features on servers
Invoke-Command -computername $Clusters.nodes -ScriptBlock {
Install-WindowsFeature -Name "Failover-Clustering","Hyper-V-PowerShell"
}
#install Hyper-V using DISM if Install-WindowsFeature fails (if nested virtualization is not enabled install-windowsfeature fails)
Invoke-Command -ComputerName $Clusters.nodes -ScriptBlock {
$Result=Install-WindowsFeature -Name "Hyper-V" -ErrorAction SilentlyContinue
if ($result.ExitCode -eq "failed"){
Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V -Online -NoRestart
}
}
#restart all servers since failover clustering in 2019 requires reboot
Restart-Computer -ComputerName $Clusters.nodes -Protocol WSMan -Wait -For PowerShell -Force
Start-Sleep 20 #Failsafe as Hyper-V needs 2 reboots and sometimes it happens, that during the first reboot the restart-computer evaluates the machine is up
#make sure computers are restarted
Foreach ($Server in $Clusters.nodes){
do{$Test= Test-NetConnection -ComputerName $Server -CommonTCPPort WINRM}while ($test.TcpTestSucceeded -eq $False)
}
#create virtual switches
foreach ($Cluster in $Clusters){
Invoke-Command -ComputerName $Cluster.Nodes -ScriptBlock {
$NetAdapters=Get-NetAdapter | Sort-Object Name
New-VMSwitch -Name $using:Cluster.vSwitchName -EnableEmbeddedTeaming $TRUE -EnableIov $true -NetAdapterName $NetAdapters.Name
}
}
#create clusters
foreach ($Cluster in $Clusters){
New-Cluster -Name $cluster.Name -Node $Cluster.Nodes -StaticAddress $cluster.IP
Start-Sleep 5
Clear-DNSClientCache
}
#add file share witness
foreach ($Cluster in $Clusters){
$ClusterName=$Cluster.Name
#Create new directory
$WitnessName=$ClusterName+"Witness"
Invoke-Command -ComputerName DC -ScriptBlock {new-item -Path c:\Shares -Name $using:WitnessName -ItemType Directory}
#create fileshare
$accounts=@()
$accounts+="corp\$($ClusterName)$"
$accounts+="corp\Domain Admins"
New-SmbShare -Name $WitnessName -Path "c:\Shares\$WitnessName" -FullAccess $accounts -CimSession DC
#Set NTFS permissions
Invoke-Command -ComputerName DC -ScriptBlock {(Get-SmbShare $using:WitnessName).PresetPathAcl | Set-Acl}
#Set Quorum
Set-ClusterQuorum -Cluster $ClusterName -FileShareWitness "\\DC\$WitnessName"
}
#Enable S2D
Enable-ClusterS2D -CimSession $Clusters.Name -Verbose -Confirm:0
#Create Volumes
Foreach ($Cluster in $Clusters){
1..$Cluster.Nodes.Count | ForEach-Object {
New-Volume -CimSession $Cluster.Name -FileSystem CSVFS_ReFS -StoragePoolFriendlyName S2D* -Size 1TB -FriendlyName "CSV$_"
}
}
#Create VMs on first cluster only
$ClusterName=$Clusters[0].Name
$vSwitchName=$Clusters[0].vSwitchName
$CSVs=(Get-ClusterSharedVolume -Cluster $ClusterName).Name
foreach ($CSV in $CSVs){
$CSV=($CSV -split '\((.*?)\)')[1]
1..3 | ForEach-Object {
$VMName="TestVM$($CSV)_$_"
Invoke-Command -ComputerName ((Get-ClusterNode -Cluster $ClusterName).Name | Get-Random) -ScriptBlock {
#create some dummy VMs
New-VM -Name $using:VMName -NewVHDPath "c:\ClusterStorage\$($using:CSV)\$($using:VMName)\Virtual Hard Disks\$($using:VMName).vhdx" -NewVHDSizeBytes 32GB -SwitchName $using:vSwitchName -Generation 2 -Path "c:\ClusterStorage\$($using:CSV)\" -MemoryStartupBytes 32MB
}
Add-ClusterVirtualMachineRole -VMName $VMName -Cluster $ClusterName
}
}
#Start VMs
Start-VM -VMName * -CimSession $Clusters[0].Nodes
#endregion
#region attempt Live Migration
#Configure kerberos constrained delegation to move from Firstcluster to SecondCluster and back
# https://technet.microsoft.com/en-us/windows-server-docs/compute/hyper-v/deploy/set-up-hosts-for-live-migration-without-failover-clustering
#define cluster names.
$Clusters="S2D-Cluster","AzSHCI-Cluster"
#configure kerberos constrained delegation for cifs and Microsoft Virtual System Migration Service, both name and FQDN
foreach ($Cluster in $Clusters){
$SourceNodes=(Get-ClusterNode -Cluster $Cluster).Name
$DestinationNodes=$clusters | ForEach-Object {if ($_ -ne $cluster){(Get-ClusterNode -Cluster $_).Name}}
Foreach ($DestinationNode in $DestinationNodes){
$HostName = $DestinationNode
$HostFQDN = (Resolve-DnsName $HostName).name | Select-Object -First 1
Foreach ($SourceNode in $SourceNodes){
Get-ADComputer $SourceNode | Set-ADObject -Add @{"msDS-AllowedToDelegateTo"="Microsoft Virtual System Migration Service/$HostFQDN", "Microsoft Virtual System Migration Service/$HostName", "cifs/$HostFQDN", "cifs/$HostName"}
}
}
}
#Switch to any authentication protocol https://blogs.technet.microsoft.com/virtualization/2017/02/01/live-migration-via-constrained-delegation-with-kerberos-in-windows-server-2016/
foreach ($Cluster in $clusters){
$ClusterNodes=(Get-ClusterNode -Cluster $Cluster).Name
Foreach ($ClusterNode in $ClusterNodes){
$GUID=(Get-ADComputer $clusternode).ObjectGUID
$comp=Get-ADObject -identity $Guid -Properties "userAccountControl"
#Flip the ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit using powershell bitwise OR operation (-bor)
$Comp.userAccountControl = $Comp.userAccountControl -bor 16777216
Set-ADObject -Instance $Comp
}
}
#Switch to kerberos authentication for live migration
foreach ($Cluster in $Clusters){
$ClusterNodes=(Get-ClusterNode -Cluster $Cluster).Name
Set-VMHost -CimSession $ClusterNodes -VirtualMachineMigrationAuthenticationType Kerberos
}
#Attempt Live Migration of one VM
$SourceClusterName="S2D-Cluster"
$DestinationClusterName="AzSHCI-Cluster"
$SourceStoragePath="C:\ClusterStorage\CSV1"
$DestinationStoragePath="C:\ClusterStorage\CSV1"
$VMNames=(Get-VM -cimsession (get-clusternode -cluster $SourceClusterName).Name | Where-Object Path -Like "$SourceStoragePath*").Name
#remove VMs from HA Resources
foreach ($VMName in $VMNames){
Get-ClusterResource -Cluster $SourceClusterName -name "Virtual Machine $VMName" | Remove-ClusterResource -force
Get-ClusterGroup -Cluster $SourceClusterName -Name $VMName | Remove-ClusterGroup -force
}
#attempt Live migration to different cluster (this will fail)
foreach ($VMName in $VMNames){
#Grab random node in cluster $DestinationClusterName
$DestinationHost=(get-clusternode -cluster $DestinationClusterName | get-random).Name
$VM=Get-VM -Cimsession (get-clusternode -cluster $SourceClusterName).Name -Name $VMName
$VM | Move-VM -DestinationHost $DestinationHost -DestinationStoragePath "$DestinationStoragePath\$($VM.Name)" -IncludeStorage
}
#endregion
#region Let's try just simply copy VMs one by one
$SourceClusterName="S2D-Cluster"
$DestinationClusterName="AzSHCI-Cluster"
$SourceStoragePath="C:\ClusterStorage\CSV1"
$DestinationStoragePath="C:\ClusterStorage\CSV1"
$VMNames=(Get-VM -cimsession (get-clusternode -cluster $SourceClusterName).Name | Where-Object Path -Like "$SourceStoragePath*").Name
# Temporarily enable CredSSP delegation to avoid double-hop issue
$Servers=(get-clusternode -cluster $SourceClusterName).Name
foreach ($Server in $Servers){
Enable-WSManCredSSP -Role "Client" -DelegateComputer $Server -Force
}
Invoke-Command -ComputerName $servers -ScriptBlock { Enable-WSManCredSSP Server -Force }
#$Credentials=Get-Credential
$password = ConvertTo-SecureString "LS1setup!" -AsPlainText -Force
$Credentials = New-Object System.Management.Automation.PSCredential ("CORP\LabAdmin", $password)
#do the move
foreach ($VMName in $VMNames){
#remove VM from HA Resources
Get-ClusterResource -Cluster $SourceClusterName -name "Virtual Machine $VMName" -ErrorAction Ignore | Remove-ClusterResource -force
Get-ClusterGroup -Cluster $SourceClusterName -Name $VMName -ErrorAction Ignore | Remove-ClusterGroup -force
#Grab random node in cluster $DestinationClusterName
$VM=Get-VM -Cimsession (get-clusternode -cluster $SourceClusterName).Name -Name $VMName
$VM | Stop-VM -Save
#Backup config
Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Copy-Item -Path "$($using:VM.Path)\Virtual Machines" -Destination "$($using:VM.Path)\Virtual Machines Bak" -Recurse}
#If there is different switch name in destination node, you should consider disconnecting vNICs first
#$VM | Get-VMNetworkAdapter | Disconnect-VMNetworkAdapter
#Remove VM
$VM | Remove-VM -Force
#Restore Config
#Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Copy-Item -Path "$($using:VM.Path)\Virtual Machines Bak\*" -Destination "$($using:VM.Path)\Virtual Machines" -Recurse}
Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Move-Item -Path "$($using:VM.Path)\Virtual Machines Bak\*" -Destination "$($using:VM.Path)\Virtual Machines"}
Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Remove-Item -Path "$($using:VM.Path)\Virtual Machines Bak\"}
#Copy machine to destination node using CredSSP
$VolumeName=$DestinationStoragePath | Split-Path -Leaf
Invoke-Command -ComputerName ($Servers | Get-Random) -Credential $Credentials -Authentication Credssp -ScriptBlock {Copy-Item -Path "$($using:VM.Path)" -Destination "\\$using:DestinationClusterName\ClusterStorage$\$using:VolumeName\" -Recurse}
#Import VM and Start
$DestinationHost=(get-clusternode -cluster $DestinationClusterName | get-random).Name
$NewVM=Import-VM -Path "$DestinationStoragePath\$($VM.Name)\Virtual Machines\$($VM.ID.GUID).vmcx" -CimSession $DestinationHost
$NewVM | Start-VM
}
#disable credssp
Disable-WSManCredSSP -Role Client
Invoke-Command -ComputerName $servers -ScriptBlock { Disable-WSManCredSSP Server }
#endregion
#region move all VMs in cluster volume by volume
$SourceClusterName="S2D-Cluster"
$DestinationClusterName="AzSHCI-Cluster"
$SourceClusterVolumes=(Get-ClusterSharedVolume -Cluster $SourceClusterName).sharedvolumeinfo.Friendlyvolumename
$DestinationClusterVolumes=(Get-ClusterSharedVolume -Cluster $DestinationClusterName).sharedvolumeinfo.Friendlyvolumename
# Temporarily enable CredSSP delegation to avoid double-hop issue
$Servers=(get-clusternode -cluster $SourceClusterName).Name
foreach ($Server in $Servers){
Enable-WSManCredSSP -Role "Client" -DelegateComputer $Server -Force
}
Invoke-Command -ComputerName $servers -ScriptBlock { Enable-WSManCredSSP Server -Force }
#$Credentials=Get-Credential
$password = ConvertTo-SecureString "LS1setup!" -AsPlainText -Force
$Credentials = New-Object System.Management.Automation.PSCredential ("CORP\LabAdmin", $password)
#do the move
Foreach ($SourceClusterVolume in $SourceClusterVolumes){
$index=$SourceClusterVolumes.IndexOf($SourceClusterVolume)
#Grab destination Volume
#adjust index if there are more volumes in source cluster than in destination
if ($index -gt ($DestinationClusterVolumes.Count-1)){
$index=$index % ($DestinationClusterVolumes.Count-1)
}
$VMNames=(Get-VM -cimsession (get-clusternode -cluster $SourceClusterName).Name | Where-Object Path -Like "$SourceClusterVolume*").Name
foreach ($VMName in $VMNames){
#remove VM from HA Resources
Get-ClusterResource -Cluster $SourceClusterName -name "Virtual Machine $VMName" -ErrorAction Ignore | Remove-ClusterResource -force
Get-ClusterGroup -Cluster $SourceClusterName -Name $VMName -ErrorAction Ignore | Remove-ClusterGroup -force
$VM=Get-VM -Cimsession (get-clusternode -cluster $SourceClusterName).Name -Name $VMName
$VM | Stop-VM -Save
#If there is different switch name in destination node, you should consider disconnecting vNICs first
#$VM | Get-VMNetworkAdapter | Disconnect-VMNetworkAdapter
#Backup config
Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Copy-Item -Path "$($using:VM.Path)\Virtual Machines" -Destination "$($using:VM.Path)\Virtual Machines Bak" -Recurse}
#Remove VM
$VM | Remove-VM -Force
#Restore Config
#Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Copy-Item -Path "$($using:VM.Path)\Virtual Machines Bak\*" -Destination "$($using:VM.Path)\Virtual Machines" -Recurse}
Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Move-Item -Path "$($using:VM.Path)\Virtual Machines Bak\*" -Destination "$($using:VM.Path)\Virtual Machines"}
Invoke-Command -ComputerName $SourceClusterName -ScriptBlock {Remove-Item -Path "$($using:VM.Path)\Virtual Machines Bak\"}
#Copy machine to destination node using CredSSP
$VolumeName=$DestinationClusterVolumes[$index] | Split-Path -Leaf
Invoke-Command -ComputerName ($Servers | Get-Random) -Credential $Credentials -Authentication Credssp -ScriptBlock {Copy-Item -Path "$($using:VM.Path)" -Destination "\\$using:DestinationClusterName\ClusterStorage$\$using:VolumeName\" -Recurse}
#Import VM and Start
$DestinationHost=(get-clusternode -cluster $DestinationClusterName | get-random).Name
$NewVM=Import-VM -Path "$($DestinationClusterVolumes[$index])\$($VM.Name)\Virtual Machines\$($VM.ID.GUID).vmcx" -CimSession $DestinationHost
$NewVM | Start-VM
}
}
#disable credssp
Disable-WSManCredSSP -Role Client
Invoke-Command -ComputerName $servers -ScriptBlock { Disable-WSManCredSSP Server }
#endregion
#region add VMs as HA Resources on destination cluster
$DestinationClusterName="AzSHCI-Cluster"
#register Azure Stack HCI first
$ClusterName=$DestinationClusterName
#download Azure module
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
if (!(Get-InstalledModule -Name Az.StackHCI -ErrorAction Ignore)){
Install-Module -Name Az.StackHCI -Force
}
#login to azure
#download Azure module
if (!(Get-InstalledModule -Name az.accounts -ErrorAction Ignore)){
Install-Module -Name Az.Accounts -Force
}
Login-AzAccount -UseDeviceAuthentication
#select context if more available
$context=Get-AzContext -ListAvailable
if (($context).count -gt 1){
$context | Out-GridView -OutputMode Single | Set-AzContext
}
#select subscription if more available
$subscriptions=Get-AzSubscription
if (($subscriptions).count -gt 1){
$SubscriptionID=($subscriptions | Out-GridView -OutputMode Single | Select-AzSubscription).Subscription.Id
}else{
$SubscriptionID=$subscriptions.id
}
#register Azure Stack HCI
$ResourceGroupName="AzureStackHCIClusters"
if (!(Get-InstalledModule -Name Az.Resources -ErrorAction Ignore)){
Install-Module -Name Az.Resources -Force
}
#choose location for cluster (and RG)
$region=(Get-AzLocation | Where-Object Providers -Contains "Microsoft.AzureStackHCI" | Out-GridView -OutputMode Single -Title "Please select Location for AzureStackHCI metadata").Location
If (-not (Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Ignore)){
New-AzResourceGroup -Name $ResourceGroupName -Location $region
}
#Register AZSHCi without prompting for creds
$armTokenItemResource = "https://management.core.windows.net/"
$graphTokenItemResource = "https://graph.windows.net/"
$azContext = Get-AzContext
$authFactory = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory
$graphToken = $authFactory.Authenticate($azContext.Account, $azContext.Environment, $azContext.Tenant.Id, $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $graphTokenItemResource).AccessToken
$armToken = $authFactory.Authenticate($azContext.Account, $azContext.Environment, $azContext.Tenant.Id, $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $armTokenItemResource).AccessToken
$id = $azContext.Account.Id
#Register-AzStackHCI -SubscriptionID $subscriptionID -ComputerName $ClusterName -GraphAccessToken $graphToken -ArmAccessToken $armToken -AccountId $id
Register-AzStackHCI -Region $Region -SubscriptionID $subscriptionID -ComputerName $ClusterName -GraphAccessToken $graphToken -ArmAccessToken $armToken -AccountId $id -ResourceName $ClusterName -ResourceGroupName $ResourceGroupName
#add VMs as HA Resources on destination cluster
$VMNames=(Get-VM -cimsession (get-clusternode -cluster $DestinationClusterName).Name).Name
foreach ($VMName in $VMNames){
Add-ClusterVirtualMachineRole -VMName $VMName -Cluster $DestinationClusterName -ErrorAction Ignore
}
#endregion
#region refresh OS on S2D cluster nodes from "NewAzSHCI" VMs - like you would reinstall OS completely
###############################
# Run all from Hyper-V host ! #
###############################
#assuming all VMs are now saved, you can simply turn off all cluster nodes and replace all disks
$VMsWithOldOS=Get-VM -Name *S2D* | Sort-Object Name
$VMsWithNewOS=Get-VM -Name *NewAzSHCI* | Sort-Object Name
foreach ($VM in $VMsWithOldOS){
$VM | Stop-VM -TurnOff
$index=$VMsWithOldOS.IndexOf($VM)
Remove-VMHardDiskDrive -VMName $VM.Name -ControllerNumber 0 -ControllerLocation 0 -ControllerType SCSI
$NewVhd=$VMsWithNewOS[$index] | Get-VMHardDiskDrive
#make sure source OS VM is shut down
$VMsWithNewOS[$index] | Stop-VM
#add disk to VM = "reinstall"
Add-VMHardDiskDrive -VMName $VM.Name -Path $NewVhd.Path
$VM | Start-VM
}
#endregion
#region Install cluster and enable Cluster-S2D
###########################
# Run all from DC Again ! #
###########################
#just recycling the same code as in first region
# variables
$Clusters=@()
$Clusters+=@{Nodes=1..4 | Foreach-Object {"NewAzSHCI$_"} ; Name="NewHCI-Cluster" ; IP="10.0.0.114" ; vSwitchName="vSwitch"}
# Install features for management
$WindowsInstallationType=Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\' -Name InstallationType
if ($WindowsInstallationType -eq "Server"){
Install-WindowsFeature -Name RSAT-Clustering,RSAT-Clustering-Mgmt,RSAT-Clustering-PowerShell,RSAT-Hyper-V-Tools
}elseif ($WindowsInstallationType -eq "Server Core"){
Install-WindowsFeature -Name RSAT-Clustering,RSAT-Clustering-PowerShell,RSAT-Hyper-V-Tools
}
# Install features on servers
Invoke-Command -computername $Clusters.nodes -ScriptBlock {
Install-WindowsFeature -Name "Failover-Clustering","Hyper-V-PowerShell"
}
#install Hyper-V using DISM if Install-WindowsFeature fails (if nested virtualization is not enabled install-windowsfeature fails)
Invoke-Command -ComputerName $Clusters.nodes -ScriptBlock {
$Result=Install-WindowsFeature -Name "Hyper-V" -ErrorAction SilentlyContinue
if ($result.ExitCode -eq "failed"){
Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V -Online -NoRestart
}
}
#restart all servers since failover clustering in 2019 requires reboot
Restart-Computer -ComputerName $Clusters.nodes -Protocol WSMan -Wait -For PowerShell -Force
Start-Sleep 20 #Failsafe as Hyper-V needs 2 reboots and sometimes it happens, that during the first reboot the restart-computer evaluates the machine is up
#make sure computers are restarted
Foreach ($Server in $Clusters.nodes){
do{$Test= Test-NetConnection -ComputerName $Server -CommonTCPPort WINRM}while ($test.TcpTestSucceeded -eq $False)
}
#create virtual switches
foreach ($Cluster in $Clusters){
Invoke-Command -ComputerName $Cluster.Nodes -ScriptBlock {
$NetAdapters=Get-NetAdapter | Sort-Object Name
New-VMSwitch -Name $using:Cluster.vSwitchName -EnableEmbeddedTeaming $TRUE -EnableIov $true -NetAdapterName $NetAdapters.Name
}
}
#create clusters
foreach ($Cluster in $Clusters){
New-Cluster -Name $cluster.Name -Node $Cluster.Nodes -StaticAddress $cluster.IP
Start-Sleep 5
Clear-DNSClientCache
}
#add file share witness
foreach ($Cluster in $Clusters){
$ClusterName=$Cluster.Name
#Create new directory
$WitnessName=$ClusterName+"Witness"
Invoke-Command -ComputerName DC -ScriptBlock {new-item -Path c:\Shares -Name $using:WitnessName -ItemType Directory}
#create fileshare
$accounts=@()
$accounts+="corp\$($ClusterName)$"
$accounts+="corp\Domain Admins"
New-SmbShare -Name $WitnessName -Path "c:\Shares\$WitnessName" -FullAccess $accounts -CimSession DC
#Set NTFS permissions
Invoke-Command -ComputerName DC -ScriptBlock {(Get-SmbShare $using:WitnessName).PresetPathAcl | Set-Acl}
#Set Quorum
Set-ClusterQuorum -Cluster $ClusterName -FileShareWitness "\\DC\$WitnessName"
}
#Enable S2D
Enable-ClusterS2D -CimSession $Clusters.Name -Verbose -Confirm:0
#endregion
#region fix volumes and import VMs
$ClusterName="NewHCI-Cluster"
$ClusterNodes=(Get-ClusterNode -Cluster $ClusterName).Name
#remove cluster disk from resources to be able to find correct ID
Get-ClusterResource -Cluster $ClusterName | Where-Object ResourceType -eq "Physical Disk" | Remove-ClusterResource -Force
#match VDisks and Cluster Available Disks, and rename
$ClusterAvailableDisks=Get-ClusterAvailableDisk -Cluster $ClusterName
foreach ($ClusterAvailableDisk in $ClusterAvailableDisks){
$VirtualDisk=Get-VirtualDisk -CimSession $ClusterName | Where-Object ObjectID -like "*$($ClusterAvailableDisk.ID)*"
$ClusterDisk=$ClusterAvailableDisk | Add-ClusterDisk
$ClusterDisk.Name="Cluster Virtual Disk ($($VirtualDisk.FriendlyName))"
}
#Add disks to CSV
Get-ClusterResource -Cluster $ClusterName | Where-Object ResourceType -eq "Physical Disk" | Where-Object Name -NotLike "Cluster Virtual Disk (ClusterPerformanceHistory)" | Add-ClusterSharedVolume
#wait a bit
Start-Sleep 20
#import all VMs
Invoke-Command -ComputerName $ClusterNodes[0] -ScriptBlock{
get-childitem C:\ClusterStorage -Recurse | Where-Object {($_.extension -eq '.vmcx' -and $_.directory -like '*Virtual Machines*') -or ($_.extension -eq '.xml' -and $_.directory -like '*Virtual Machines*')} | ForEach-Object -Process {
Import-VM -Path $_.FullName -ErrorAction SilentlyContinue
}
}
#endregion
#region add VMs as HA Resources on destination cluster
$DestinationClusterName="NewHCI-Cluster"
#register Azure Stack HCI first
$ClusterName=$DestinationClusterName
#download Azure module
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
if (!(Get-InstalledModule -Name Az.StackHCI -ErrorAction Ignore)){
Install-Module -Name Az.StackHCI -Force
}
#login to azure
#download Azure module
if (!(Get-InstalledModule -Name az.accounts -ErrorAction Ignore)){
Install-Module -Name Az.Accounts -Force
}
Login-AzAccount -UseDeviceAuthentication
#select context if more available
$context=Get-AzContext -ListAvailable
if (($context).count -gt 1){
$context | Out-GridView -OutputMode Single | Set-AzContext
}
#select subscription if more available
$subscriptions=Get-AzSubscription
if (($subscriptions).count -gt 1){
$SubscriptionID=($subscriptions | Out-GridView -OutputMode Single | Select-AzSubscription).Subscription.Id
}else{
$SubscriptionID=$subscriptions.id
}
#register Azure Stack HCI
$ResourceGroupName="AzureStackHCIClusters"
if (!(Get-InstalledModule -Name Az.Resources -ErrorAction Ignore)){
Install-Module -Name Az.Resources -Force
}
#choose location for cluster (and RG)
$region=(Get-AzLocation | Where-Object Providers -Contains "Microsoft.AzureStackHCI" | Out-GridView -OutputMode Single -Title "Please select Location for AzureStackHCI metadata").Location
If (-not (Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Ignore)){
New-AzResourceGroup -Name $ResourceGroupName -Location $region
}
#Register AZSHCi without prompting for creds
$armTokenItemResource = "https://management.core.windows.net/"
$graphTokenItemResource = "https://graph.windows.net/"
$azContext = Get-AzContext
$authFactory = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory
$graphToken = $authFactory.Authenticate($azContext.Account, $azContext.Environment, $azContext.Tenant.Id, $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $graphTokenItemResource).AccessToken
$armToken = $authFactory.Authenticate($azContext.Account, $azContext.Environment, $azContext.Tenant.Id, $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $armTokenItemResource).AccessToken
$id = $azContext.Account.Id
#Register-AzStackHCI -SubscriptionID $subscriptionID -ComputerName $ClusterName -GraphAccessToken $graphToken -ArmAccessToken $armToken -AccountId $id
Register-AzStackHCI -Region $Region -SubscriptionID $subscriptionID -ComputerName $ClusterName -GraphAccessToken $graphToken -ArmAccessToken $armToken -AccountId $id -ResourceName $ClusterName -ResourceGroupName $ResourceGroupName
#add VMs as HA Resources on destination cluster
$VMNames=(Get-VM -cimsession (get-clusternode -cluster $DestinationClusterName).Name).Name
foreach ($VMName in $VMNames){
Add-ClusterVirtualMachineRole -VMName $VMName -Cluster $DestinationClusterName -ErrorAction Ignore
}
#endregion

Просмотреть файл

Просмотреть файл

@ -9,22 +9,17 @@
Install-Module -Name VMFleet -Force
Install-Module -Name PrivateCloud.DiagnosticInfo -Force
#Make sure Hyper-V is installed (to be able to work with VHD)
$Result=Install-WindowsFeature -Name "Hyper-V" -ErrorAction SilentlyContinue
if ($result.ExitCode -eq "failed"){
Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V -Online -NoRestart
}
#endregion
#region Configure VMFleet prereqs
#Create Volumes
Foreach ($Node in $Nodes){
if (-not (Get-Virtualdisk -CimSession $ClusterName -FriendlyName $Node)){
if (-not (Get-Virtualdisk -CimSession $ClusterName -FriendlyName $Node -ErrorAction Ignore)){
New-Volume -CimSession $Node -StoragePoolFriendlyName "S2D on $ClusterName" -FileSystem CSVFS_ReFS -FriendlyName $Node -Size $VolumeSize
}
}
if (-not (Get-Virtualdisk -CimSession $ClusterName -FriendlyName Collect)){
if (-not (Get-Virtualdisk -CimSession $ClusterName -FriendlyName Collect -ErrorAction Ignore)){
New-Volume -CimSession $CLusterName -StoragePoolFriendlyName "S2D on $ClusterName" -FileSystem CSVFS_ReFS -FriendlyName Collect -Size 100GB
}
@ -64,9 +59,10 @@
Invoke-Command -ComputerName $Nodes[0] -Credential $Credentials -Authentication Credssp -ScriptBlock {
Install-Fleet #as vmfleet has issues with Install-Fleet -ClusterName https://github.com/microsoft/diskspd/issues/157
#It's probably more convenient to run this command on cluster as all VHD copying will happen on cluster itself.
#Grab nubmer of Logical Processors per node divided by 2 (Hyper thread CPUs)
$NumberOfVMs=(Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfLogicalProcessors/2
New-Fleet -BaseVHD "c:\ClusterStorage\Collect\$using:VHDName" -VMs $using:NumberOfVMs -AdminPass P@ssw0rd -Admin Administrator -ConnectUser corp\LabAdmin -ConnectPass LS1setup!
#Grab nubmer of Logical Processors per node divided by 2 (Hyper thread CPUs) - no need to do it, this will happen automagically if -VMs not specified
#$NumberOfVMs=(Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfLogicalProcessors/2
#New-Fleet -BaseVHD "c:\ClusterStorage\Collect\$using:VHDName" -VMs $using:NumberOfVMs -AdminPass P@ssw0rd -Admin Administrator -ConnectUser corp\LabAdmin -ConnectPass LS1setup!
New-Fleet -BaseVHD "c:\ClusterStorage\Collect\$using:VHDName" -AdminPass P@ssw0rd -Admin Administrator -ConnectUser corp\LabAdmin -ConnectPass LS1setup!
}
# Disable CredSSP
@ -98,4 +94,29 @@
# Disable CredSSP
Disable-WSManCredSSP -Role Client
Invoke-Command -ComputerName $nodes -ScriptBlock { Disable-WSManCredSSP Server }
#endregion
#region Remove Fleet
# Temporarily enable CredSSP delegation to avoid double-hop issue
foreach ($Node in $Nodes){
Enable-WSManCredSSP -Role "Client" -DelegateComputer $Node -Force
}
Invoke-Command -ComputerName $Nodes -ScriptBlock { Enable-WSManCredSSP Server -Force }
$password = ConvertTo-SecureString "LS1setup!" -AsPlainText -Force
$Credentials = New-Object System.Management.Automation.PSCredential ("CORP\LabAdmin", $password)
Invoke-Command -ComputerName $Nodes[0] -Credential $Credentials -Authentication Credssp -ScriptBlock {
Remove-Fleet
}
# Disable CredSSP
Disable-WSManCredSSP -Role Client
Invoke-Command -ComputerName $nodes -ScriptBlock { Disable-WSManCredSSP Server }
# Remove CSVs
foreach ($Node in $Nodes){
Remove-VirtualDisk -FriendlyName $Node -CimSession $ClusterName -Confirm:0
}
Remove-VirtualDisk -FriendlyName Collect -CimSession $ClusterName -Confirm:0
#endregion

Просмотреть файл

@ -274,10 +274,10 @@ If (-not $isAdmin) {
}
$ISOServer = Mount-DiskImage -ImagePath $ServerISOItem.FullName -PassThru
}else{
WriteInfoHighlighted "Please select ISO image with Windows Server 2016, 2019 or Server Insider"
WriteInfoHighlighted "Please select ISO image with Windows Server 2016, 2019, 2022 or Server Insider"
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
Title="Please select ISO image with Windows Server 2016, 2019 or Server Insider"
Title="Please select ISO image with Windows Server 2016, 2019, 2022 or Server Insider"
}
$openFile.Filter = "iso files (*.iso)|*.iso|All files (*.*)|*.*"
If($openFile.ShowDialog() -eq "OK"){
@ -398,7 +398,7 @@ If (-not $isAdmin) {
VHDName="Win2022Core_G2.vhdx"
Size=30GB
}
}elseif ($BuildNumber -ge 17744 -and $SAC){
}elseif ($BuildNumber -gt 20348 -and $SAC){
$ServerVHDs += @{
Kind = "Core"
Edition="2"
@ -409,7 +409,7 @@ If (-not $isAdmin) {
if ($LabConfig.DCEdition -gt 2){
$LabConfig.DCEdition=2
}
}elseif ($BuildNumber -ge 17744){
}elseif ($BuildNumber -gt 20348){
#Windows Sever Insider
$ServerVHDs += @{
Kind = "Full"

Просмотреть файл

@ -162,6 +162,9 @@ If (-not $isAdmin) {
"AzSHCI21H2_G2.vhdx"
}
}
if ($BuildNumber -GT 20348){
$tempvhdname="AzSHCIInsider_$BuildNumber.vhdx"
}
}elseif (($Edition -like "*Server*Core*") -or ($Edition -like "Windows Server * Datacenter") -or ($Edition -like "Windows Server * Standard")){
$tempvhdname = switch ($BuildNumber){
7600 {
@ -295,7 +298,7 @@ If (-not $isAdmin) {
}
}
if ($BuildNumber -GT 22000){
$tempvhdname="Win10Insider_$BuildNumber.vhdx"
$tempvhdname="Win11Insider_$BuildNumber.vhdx"
}
}
}