Category Archives: VMware

How To: Windows 2008R2 to 2012R2 upgrade for IIS Servers [CONFIRMED VALID UPGRADE]

How To: Upgrade from Windows 2008R2 to Windows 2012R2 running IIS and Windows Services

We’ve been tasked with upgrading all our 2008R2 Windows Servers to Windows 2012R2. This is due to Microsoft removing support for Windows 2008R2 in January 2020. We’ve performed this upgrade on all our non prod servers first to iron out the issues with 2008 upgrades. I’ll post the errors I ran into when I gather them up but once you go through the steps, it’s VERY easy to upgrade if you follow these simple steps:

Read through this multiple times before you start. There are verification steps you should follow before you start.

2012R2 Upgrade Procedures:

  1. Verify your backup of your server. In a perfect world (which I live in), your 2008R2 will be a virtual machine running on VMware and the backups are automatic the evening before.
  2. Create a local administrator. This is to ensure that if your 2008 upgrade to 2012 doesn’t go well, or it gets removed from the domain, you still have a local user that you’re confident works to get you into the server
  3. Check the C: drive size of the computer. You will need to expand it to have somewhere like 40GB of free space for the upgrade
  4. Check the system log and app logs for errors. You want to have a baseline of any errors occuring on your system so you’re aware of what errors are due to the upgrade to Windows 2012 and what was existing. Please don’t skip this step
  5. Take a snapshot of your server. Yes, you have a backup but a snapshot will ensure that if you need to roll back from Windows 2012R2 back to Windows 2008R2, you can do it immediately. You also won’t have to bother your backup administrator either 🙂
  6. If your servers are part of a load balanced system, Remove it from traffic. Drain and halt the server and verify no traffic is going to it. You should also verify that you can hit the servers websites prior to doing the upgrade as well. We use HOSTS files for this and it works fairly well. Also, if you terminate SSL/TLS at the load balancer, you should also add a VIP with the same SSL/TLS certificate on it so you can mimic your traffic like production. Many people try and hit their server directly and if you’re terminating traffic in front of your server and pass traffic back on port 80, chances are, your browser won’t allow you to do this due to HSTS implemented by your developers. Here is a document explaining HSTS of you need to know more: https://www.globalsign.com/en/blog/what-is-hsts-and-how-do-i-use-it/
  7. Perform the upgrade to 2012R2. Depending on the server’s power (CPU’s and Memory) along with how much data is on it. This upgrade will take around 2 – 5 hours to complete Also, do this from VMware console and NOT from RDP. I repeat… Do this from VMware console and NOT from RDP. If you don’t understand this, you need to before you start this upgrade.
  8. Once the upgrade is complete. Run updates over and over and over until all updates are installed. At this point, if .NET 4.8 isn’t installed, you will get lots of errors running Server Manager and IIS. Things just won’t work correctly. This is to be expected
  9. Perform POST installations of required software. These include:
    1. .NET 4.8 (Download from here: https://docs.microsoft.com/en-us/dotnet/framework/deployment/deployment-guide-for-developers)
    2. HTTP Platform Handler (Download from here: https://www.iis.net/downloads/microsoft/httpplatformhandler)
    3. .net-hosting 2.2.7 (If your sites use this) (Download from here: https://dotnet.microsoft.com/download/dotnet-core/2.2)
    4. URL Rewrite (Download from here: https://www.iis.net/downloads/microsoft/url-rewrite)
    5. Enable the SchUseStrongCrypto property in the Windows registry: If your server does TLS SSL connections outbound to API’s like UPS, Paypal, Braintree or any other site, you will need to force your .NET software to connect using TLS 1.1 or TLS 1.2. To do this, there is a simple registry entry that needs to be added.
      1. Start Regedit and navigate to:
        HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NetFramework\v4.0.30319
      2. Right click in the right pane and create a new DWORD (32-bit) value and name it SchUseStrongCrypto
      3. Enter the Value in the data field of 1 and it should be Hexadecimal. Click on OK
      4. Repeat steps 1-3 for the following WOW6432Node located here:
        HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319
  10. Reboot the server
  11. Check system logs for new errors
  12. Check Application logs for new errors
  13. Verify IIS and Windows services are running
  14. Verify Domain membership is valid. If it isn’t, re-add it to the domain
  15. Perform smoke testing to your server. Again, if you’re load balanced, you would have created smoke vips on your load balancer to point to the new server. Use the HOSTS file entries to smoke test your server.
  16. Request end to end testing from your Software Quality Engineers or Test Engineers
  17. Check the size of your C: drive again. Make sure you’re not out of space
  18. If there are any servers that connect to this server via UNC or via API’s, you should consider rebooting them now. Also, check these servers for connection errors. We’ve seen our servers that connect via \\server\share can’t connect until you reboot them. Do this now!
  19. Once your verification is complete, swap in your new server in your load balancer and pull out the others that haven’t been upgraded. Run and test. A few days.
  20. Remove snapshots when you’re comfortable
  21. Remove the Temporary Admin account that you created
  22. Rinse and Repeat

Conclusion:

I’ve performed this upgrade process for Windows 2008R2 to Windows 2012 many times and these are the gold standard for upgrading a server that is running IIS and Windows Services. Make sure you have a roll back plan and perform that roll back on your development servers FIRST. So, upgrade, test, roll back. Then Upgrade again.

Move a Virtual Machine from one host to another

After building a new set of VMware ESX servers in a new vCenter cluster, I was tasked with moving around 200 virtual servers from the old cluster to the new cluster. To do this in an orderly fashion and to make sure I didn’t miss a step, I turned to Powershell to help me accomplish the task. The below script does the following:

  • Validates that you’re logged in using an admin account. Hopefully, you are and your naming convention for all your admin accounts is the same. Simply edit that part to match your convention or comment it out
  • You then Enter the server name and it fetches the Cluster, Host and Server information from VMWare.
  • The script then queries VMware vSphere for the clusters available and puts them in a list for selection.
  • You are then presented with a list of hosts in that cluster to select the destination server to move the virtual server to.
  • Then it allows you to review what you’re going to do before any servers are shutdown, moved, VMware tools upgrade and and final reboot.
  • Sometimes the script gives some errors at the end as it has a hard time determining if the server is back online. Not a big deal and everything works great!
$starttime = get-date
 
#Region Validate Admin Account
Clear-Host
Write-Host "Validating this is running as an `"Admin`" account."
# If you use a naming convention in your administrative accounts, change this next line to check for that convention
IF ($ENV:USERNAME -notlike "*ADMIN") { THROW "SCRIPT MUST BE RUN WITH ADMIN ACCOUNT." }
 
Write-Host "Good Job! You're using your ADMIN account!!"
 
#EndRegion
 
#Region Gather Migration Information
 
#Region Connecting to VMWare
Write-Host "Adding VMWare Snapin."
Write-Host ""
 
IF ( -NOT ( Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue )) { Add-PSSnapin "VMware.VimAutomation.Core" }
TRY { Disconnect-VIServer -Server * -Force -Confirm:$FALSE -ErrorAction SilentlyContinue } CATCH { }
# Put in your FQDN of your virtual center server below
Connect-VIServer -Server FQDN.OF.VIRTUALCENTER -WarningAction SilentlyContinue | Out-Null
 
#EndRegion
 
#Region Get Server Info
# Search for server to move
$UserEntryVM = Read-Host "Enter the Virtual Machine you would like to move"
IF ( -NOT (Get-VM $UserEntryVM)) { THROW "Could not find $UserEntryVM." }
$VMToMove = Get-VM $UserEntryVM
 
#EndRegion
 
#Region Source Cluster And Host
# Get Cluster and VMHost server is on
 
$SourceCluster = $VMToMove.VMHost.Parent
$SourceHost = $VMToMove.VMHost
Write-Host
Write-Host "The Details of the Source machine are:"
Write-Host
Write-Host "Server to Move:`t`t$VMToMove"
Write-Host "Source Cluster Name:`t$SourceCluster"
Write-Host "Source Host:`t`t$SourceHost"
Write-Host ""
$UserResponse = Read-Host "Is This Informaiton Correct? (y/n)"
IF ($UserResponse.length -ne 0) {
IF ("y","Y" -NotContains $UserResponse) { THROW "INVALID ENV."}
}
 
#EndRegion
 
#Region Destination Cluster And Host
# Gather Destination VMWare Host Information
Write-Host
Write-Host "Which Cluster would you like to move $VMToMove to?"
$ESXClusters = (Get-Cluster)
 
$i = 0
FOREACH ( $Cluster IN $ESXClusters )
{
$i++
write-host "`t$i) $Cluster"
 
}
Write-Host ""
[int]$UserInput = Read-Host "Please make selection above (1 - $i)"
$ChosenCluster = $ESXClusters[($UserInput-1)]
 
$ClusterHosts = ( Get-VMHost -State Connected -Location "$ChosenCluster" )
Write-Host
Write-Host "This list does not list hosts in Maintenance Mode"
Write-Host "Which Host would you like to move $VMToMove to?"
$i = 0
FOREACH ( $ESXHost IN $ClusterHosts )
{
$i++
write-host "`t$i) $ESXHost"
 
}
Write-Host ""
[int]$UserInput = Read-Host "Please make selection above (1 - $i)"
$ChosenHost = $ClusterHosts[($UserInput-1)]
 
#EndRegion
 
#Region Validate Input
 
# Clear-Host
Write-Host ""
Write-Host "Below is what you want to do:"
Write-Host "-----------------------------"
Write-Host "Server To Move:`t`t$VMToMove"
Write-Host "Source Cluster:`t`t$SourceCluster"
Write-Host "Source Host Name:`t$SourceHost"
Write-Host ""
Write-Host "The Details of Destination ESX Host are:"
Write-Host "----------------------------------------"
Write-Host "Destination Cluster:`t$ChosenCluster"
Write-Host "Destination Host:`t$ChosenHost"
Write-Host ""
$UserMoveResponse = Read-Host "IS ALL THIS INFORMATION CORRECT? (y/n)"
IF ($UserMoveResponse.length -ne 0) {
IF ("y","Y" -NotContains $UserMoveResponse) { THROW "INVALID ENV."}
}
 
#EndRegion
 
#EndRegion
 
#Region Moving Server, Reboot, Update VMWare Tools
 
# Shutdown VM
Write-Host "Shutting Down $VMToMove"
Shutdown-VMGuest $VMToMove -Confirm:$false
WHILE ( $VMState = get-vm $VMToMove | WHERE {$_.PowerState -ne "PoweredOff"}) {start-sleep -Seconds 5}
Write-Host "$VMToMove is now off, beginning move from $SourceHost to $ChosenHost"
 
# Move VM
Get-VM $VMToMove | Move-VM -destination (Get-VMHost "$ChosenHost") -Confirm:$false
 
# Validate the move
 
# Power On VM
start-vm $VMToMove -Confirm:$false
WHILE ( $VMState = get-vm $VMToMove | WHERE {$_.PowerState -ne "PoweredOn"}) {start-sleep -Seconds 5}
WHILE ( Get-Task | WHERE {$_.Name -eq "PowerOnVM_Task" -and $_.State -ne "Success" } ) { Start-Sleep -Seconds 5 ; Get-VMQuestion | Set-VMQuestion –Default -Confirm:$False }
Write-Host "$VMToMove is powering up. This should take a minute"
 
# update vmware tools
WHILE ( -NOT ( test-connection $VMToMove -quiet ) ) {start-sleep -Seconds 5}
DO {start-sleep -Seconds 45} WHILE ( get-service -ComputerName $VMToMove -name VMTools | WHERE {$_.status -ne "running"})
Start-Sleep -Seconds 15
Write-Host "Server is online, trying to update tools..."
Update-Tools $VMToMove
#EndRegion
Write-Host "Server is rebooting after VMWare Tools Install..."
DO {start-sleep -Seconds 15} WHILE (!( test-connection $VMToMove ))
$TimeSpan = New-TimeSpan -Start $starttime
Write-Host "Server should be up..."
Write-Host ""
Write-Host "Pretty cool... Huh? This move took $TimeSpan.Minutes,$TimeSpan.Seconds"
Write-Host ""
Write-Host "You're Done! Please VALIDATE that the machine is running :)"