Upgrading my Win8 beta server to Windows 2012

as yesterday the RC of the Windows 2012 came I thought i would give it a try.

First of all, i wanted to test if I could upgrade my win8 beta server to the Windows 2012 RC but as you can see on the picture from the installation this is not possible. So what to do, as I had two nodes i live migrated my VM´s to the other win8 beta and did a fresh install.

When it was finished I wanted to add the server to the domain and of course this should be done with powershell. When installing you all know that the OS get a not so friendly name so with the parameter -NewName I rename it at the same time as I add it to the domain.

Next step was of course to add the Hyper-V role,

And what to do next, well i want to live migrate my VM´s from my other node but that was unfortunately not possible 🙁 cause of some kind of mismatch with the protocol as you can see on my next screendump

Ok so my next plan was to export the VM´s and then import them, this also with powershell, but as the win8 beta set the dynamic memory maximum to 2 TB i got a configuration issue so I had to handle that before i had an successfull import

After this I could import it ( notice though I could not use the parameter -copy when using -CompabilityReport, so I had to manually copy the VM to the Hyp31 server )

Good luck in your migration to the Windows 2012 RC 🙂

PowerShell to check Automatic Windows services after patch Tuesday

I did not get this idea all by my self, a customer I was at for a couple of weeks ago showed me a small script he had to check the services set to automatic after patching to see that they actually was running again.

I thought this could be somewhat more sophisticated done, so I created a script function that can handle single servers or an array of servers and in the script you can either start all services that are stopped or select just the ones you want, you can also in the function add services that you know are not important.

As you can see, I can get the servers from the Active Directory, In this example I have created a OU that contains the servers I want to check. I can also check for example in VMware with PowerCLI and getting an array of running VM´s. This can also be done on my Hyper-V environment with SCVMM. The different arrays I collect is just to get the server names and then I do an Get-wmiObject on the servers.

Here in this screen dump I check the computers in my AD, As you can see I select (N)o and that mean that I want all services that are not running and set to automatic to be started

In this next example I check the VM´s in my VMware vSphere environment

In this last example where i query a SCVMM server for the VM´s on the Hyper-V cluster I use the -AutoRestart parameter to start up all the services that the function finds.

And here is the powershell function, the tricky part here was to get the starting of services remote working and I had to use the -InputObject command as I did not get the pipeline of Get-Service -Computer xyz -Name Spooler | Start-Service to work.

function Check-Service{
<#
.SYNOPSIS
Check if Autostart Services has not started after patching

.DESCRIPTION
Use this function to check that all autostart services have started on the servers after patching

.PARAMETER  xyz 

.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-05-28
#>
    param (
   [Parameter(Position=0,Mandatory=$true,HelpMessage="A server",
    ValueFromPipeline=$True)]
    $Servers,
	[switch]$AutoRestart
    )
	
	$report = @()
	$IgnoreServices = "ShellHWDetection","clr_optimization_v4.0.30319_32","clr_optimization_v4.0.30319_64","sppsvc"
	
	if ($Servers.GetType().Name -eq "String"){
		$Services = Get-WmiObject -ComputerName $Servers -Class win32_service -ErrorAction SilentlyContinue | where {$_.Startmode -EQ "Auto" -and $_.State -NE "Running"}
		if ($Services -ne $null) {
			foreach ($Service in $Services){
				if(!($IgnoreServices -contains $Service.Name)){
					$data = New-Object PSObject -property @{
						Server = $Servers
						Name = $Service.Name
						StartMode = $Service.StartMode
						State = $Service.State
					}
				
				$report +=$data
				}
			}
		}
	}else{
		foreach ($Server in $Servers){	
			$Services = Get-WmiObject -ComputerName $Server.Name -Class win32_service -ErrorAction SilentlyContinue | where {$_.Startmode -EQ "Auto" -and $_.State -NE "Running"}
			if ($Services -ne $null) {
				foreach ($Service in $Services){
					if(!($IgnoreServices -contains $Service.Name)){
						$data = New-Object PSObject -property @{
							Server = $Server.Name
							Name = $Service.Name
							StartMode = $Service.StartMode
							State = $Service.State
						}
					
					$report +=$data
					}
				}	
			} else {
				Write-Host "Could not query server: $Server"
			}
		}
	}
	
	$report 
	if($AutoRestart){
			$report |%{ Start-Service -InputObject (Get-Service -ComputerName $_.Server -Name $_.Name)}
	}else{
		if($report -ne $null){
			Write-Host "Do you want to select which services to start? (Y) (N) (Q):"
			$select = Read-Host
			if ($select -eq "Y"){
				foreach ($item in $report){
					Write-Host "Start service " $item.Name " on server" $item.Server " (Y) (N)"
					$restart = Read-Host
					if ($restart -eq "Y"){
						Start-Service -InputObject (Get-Service -ComputerName $item.Server -Name $item.Name)
					}
				}
			}elseif($select -eq "N"){
				$report |%{ Start-Service -InputObject (Get-Service -ComputerName $_.Server -Name $_.Name)}
			}
		}
	}
}

Good luck in finding services that should be running in your environment 🙂
 

Shrink HyperV virtual hard disk Win8 / Win2012 with PowerShell

I read this post by Ben (Virtual PC Guy) Armstrong about shrinking a virtual hard disk and thought this should be done with powershell.

So first I have to shrink the partition inside the VM, for this I use the New-CIMSession (instead of powershell remoting and such) and then I shut down the VM and shrink the VHDx file, As someone correctly noted, this shrink of the virtual disk file is only possible when using the new VHDx format.

The VM is part of the same domain as the hyper-V server from which I am running the script, this made it easier to make a cim connection. The VM is also a Win 8 beta cause I need the latest win framework with powershell 3.

As you can see, the disk in my VM is 60 GB and I want to shrink it to the minimum size * 20% (so i get at least some space left 😉

Now I will run my little script and here is what that looks like

# vNiklas Masterblaster shrink
#
# Niklas Akerlund / 2012-05-13

$VM = "Shrink8"

$cim = New-CimSession $VM

$partitionC = Get-Partition -CimSession $cim -DriveLetter C

$newSize = ($partitionC | Get-PartitionSupportedSize).SizeMin*1.20

Resize-Partition -PartitionNumber $partitionC.PartitionNumber -DiskNumber $partitionC.DiskNumber -Size $newSize -CimSession $cim

Get-Volume C -CimSession $cim

$VM = Get-VM $VM

Stop-VM $VM

$hdd = $VM | Get-VMHardDiskDrive

Resize-VHD -Path $hdd.Path -ToMinimumSize

Start-VM $VM

And here you can see the result, a quite simple solution..

Good luck in your shrinking 🙂

Update:  I totally missed that Ben had done a post about doing it with powershell, just after his other post when i was making this post… At least my solution show how to connect to a VM with CIM 🙂

 

Bare metal deploy with SCVMM 2012 fail with error 800b0109 in WinPE

Today I was at a customer and upgraded their VMM 2012 from RC to RTM. We got an issue when trying to run a bare metal deploy after the upgrade, at first we did not understand what was causing the error, but my suspicion was on the winpe that was published by VMM in the WDS PXE.

Here is the error in the VMM Console also

And then i used PowerShell to update the VMM WinPE that resides in the WDS, this because their environment had new HP blades and i needed to add a nic driver. If you do not need to add anything to the winpe you can right click on the VMM console and the PXE  and you find a selection “Update WinPE Image” this will use an image from the WAIK installed on the VMM Server. Here is the link for the powershell cmdlet that updates the WinPE

The Powershell I ran was as below, I had to run the dism tools with elevated rights, this can be done by right click on the Powershell console and “Run As Administrator”

Import-Module "C:\Program Files\Microsoft System Center 2012\Virtual Machine Manager\bin\psModules\virtualmachinemanager\virtualmachinemanager.psd1"
Get-SCVMMServer localhost
$mountdir = "E:\mount"

$winpeimage = "E:\temp\custom_winpe.wim"

$winpeimagetemp = $winpeimage + ".tmp"

mkdir "E:\mount"

copy $winpeimage $winpeimagetemp

dism /mount-wim /wimfile:$winpeimagetemp /index:1 /mountdir:$mountdir

$path = "E:\temp\drivers\be2nd62.inf" # $driver.sharepath
dism /image:$mountdir /add-driver /driver:$path

Dism /Unmount-Wim /MountDir:$mountdir /Commit

publish-scwindowspe -path $winpeimagetemp

Here is a link to the technet forum where I found another guy having the same issue, whom I helped.

After updating the WinPE we tried to do a new bare metal deploy and this time we had no issues with the certificate.

 

VMware vCloud Director vApp and DRS cluster affinity with PowerCLI

To fully utilize the performance in a vApp in vCloud Director I got the task to create an affinity rule based on the VMs in the vApp. This can be the case for example when you have VMs in an vApp that exchange high loads of data. In our case we have virtual ESXi Servers that have a vsa for shared storage and need good performance when deploying VM´s and storage vMotion etc.

When deploying several vApps from the same template it is not just to run Get-CIVM and then use the VM name returned to run Get-VM for the correlation between the VM in VCD and in vCenter, as you can see in the screendumps these two have the same name but followed with an identifier from vCD in the vSphere Client. This is also described in the vSphere blog.

The fine part is that the MoRef is unique (in the relation one vcd <-> one vcenter) so I can check on that which VMs in the vCenter belongs to the same vCloud Director vApp.

I got the code for the MoRef in this community post.

And here is my script

<#
.Synopsis
   Add an affinity rule for a vCloud Director vAPP
.DESCRIPTION
   This function takes a vApp as parameter and creates an affinity rule for them to keep them together
.EXAMPLE
   Add-CIVAppAffinity -CIVApp Green01
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-05-03
#>
function Add-CIVAppAffinity
{
    Param
    (
        # Parameter for the vAPP
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $CIVApp,

        # If the rule should apply on a different cluster
        $Cluster = "vCD-Cluster"
    )

	$pod = Get-CIVapp $CIVApp
	if ($pod){
		$PodVMs = Get-CIVM -VApp $pod
		$VMs = @()
		$Cluster = Get-Cluster $Cluster
		Foreach ($PodVM in $PodVMs) { 
			$VMname = $PodVM.Name + "*"
			$VM =  Get-VM $VMname | where {$_.ExtensionData.MoRef.Value -eq $PodVM.ExtensionData.VCloudExtension[0].Any[0].VmVimObjectRef.MoRef}
			$VMs +=$VM
		}

		if (!(Get-DrsRule -Cluster $Cluster -Name $pod.Name -ErrorAction SilentlyContinue)){ 
			New-DrsRule -Name $pod.Name -Cluster $Cluster -KeepTogether $true -VM $VMs
		}else{
			Remove-DrsRule -Rule (Get-DrsRule -Cluster $Cluster -Name $pod.Name) -Confirm:$false
			New-DrsRule -Name $pod.Name -Cluster $Cluster -KeepTogether $true -VM $VMs
		}
	}
}

And when checking the cluster i can see that my DRS affinity rule has been created and the VMs have been migrated to the same host

It is not so extensive but it helps us with the case to create DRS affinity on the VMs in a particular vApp 🙂 , The Rule is deleted when the vApp is removed, I have an extra check in the script and remove it if it still exist of some reason.

 

A PowerShell function for Snapshot reporting in VMM2012

Hello

I am in the hotel waiting for the MMS 2012 to start so there is time for some automation ;-). Last week when I was teaching a course one of the attendes said after I showed the custom value function, that he also wanted a similar function for easy in the console check how many snapshots every VM had. In the VMM 2012 console I have not found an built-in function to actually show this.

I have modified the function and created the run script, this is scheduled to run once a hour so you have a updated view of your environment. At least in the Hyper-V for Windows 2008 R2 it is not recommended to use in production.

It is quite easy to create a new custom property that we then will populate,

New-SCCustomProperty -Name "Snapshot Count" -Description "" -AddMember @("VM")

In the GUI there is no way to remove a custom property, I can only remove it from assigned properties. During the course I created an property just for showing and want to get rid of it. Of course there is a powershell cmdlet for that:

Get-SCCustomProperty -Name "Muuuu" | Remove-SCCustomProperty

But now to the part of getting the script to show snapshots (yes I know, in VMM it is called Checkpoints but i refuse to call it that)

First I have the PowerShell function

function Set-CVSnapShot{
<#
.SYNOPSIS
Function to Update custom values for VM´s in VMM 2012
 
.DESCRIPTION
Use this function to  set the custom value Snapshot count
 
.PARAMETER  VMs
Use this parameter to update just that VM´s custom snapshot value
 
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-04-16
#>
    param (
   [Parameter(Position=0,HelpMessage="A virtual machine pleaze",
    ValueFromPipeline=$True)]
    $VMs = " "
    )
   
  	if ($VMs -eq " "){
    	$VMs = Get-SCVirtualMachine
	}else{
		$VMs = Get-SCVirtualMachine  $VMs
	}
	
  	$CustomSnapShot = Get-SCCustomProperty -Name "Snapshot Count"
   
	foreach ($VM in $VMs){
		$count = ($VM | Get-SCVMCheckpoint).Count
		
	    if($count -ne $null){
	        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $CustomSnapShot -Value $count 
	    }else{
	        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $CustomSnapShot -Value 0 
	    }
   }
}

then I have a very easy script that I task scheduled in my VMM server

# Script to use for scheduled updates of Custom values
#
# Niklas Akerlund / RTS 2012-04-16

ipmo 'C:\Program Files\Microsoft System Center 2012\Virtual Machine Manager\bin\psModules\VirtualMachineManager' | Out-Null

. .\Set-CVSnapshot.ps1
Set-CVSnapshot

And in the VMM Console it looks like this

I will talk to some VMM responsibles at MMS and see if they find an interest and build the view instead of me running it in a sheduled task (as the information is there in the database)

A PowerCLI function to manage VMware vSphere Licenses

As always ( or at least in my world) you should do everything in powershell/powerCLI. Now the turn comes to handling licensing in VMware vSphere.

I searched the web and found some information from Luc Dekens post and from Joe Keegan post. I also used the Onyx VMware fling to get some more functionality.

I decided to do some powershell functions and came up with the following, I have created three functions that can do some magic with your licenses

  • Get-vLicense  – query the vCenter for licenses
  • Add-vLicense – add a license or assign an existing license to a host/vCenter
  • Remove-vLicense – remove a license that is not in use

Of course there might be other things regarding licensing i have forgot but see this as a version 0.1 and that you can give me input on what to add or change

Here you can see how the function get the information:

You have to bare with me and my paintbrush skills, but I cannot show my license keys on the Internet 🙂

I can also use a switch to just show the ones that are not used with

Get-vLicense -showUnused

I would like to move my hosts to the new license that i have that has unlimited cores

I can also in the Add function just add without assigning the license right now just use the -AddKey switch

And if I want to remove the unused license I  use the following function, It can utilize a pipeline parameter as you see

 

And here is the whole code for the functions:

function Get-vLicense{
<#
.SYNOPSIS
Function to show all licenses  in vCenter
 
.DESCRIPTION
Use this function to get all licenses in vcenter
 
.PARAMETER  xyz 
 
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-28
#>
	param (
		[Parameter(ValueFromPipeline=$True, HelpMessage="Enter the license key or object")]$LicenseKey = $null,
		[Switch]$showUnused,
		[Switch]$showEval
		)
	$servInst = Get-View ServiceInstance
	$licenceMgr = Get-View $servInst.Content.licenseManager
	if ($showUnused -and $showEval){
		$licenses = $licenceMgr.Licenses | where {$_.EditionKey -eq "eval" -or $_.Used -eq 0}
	}elseif($showUnused){
		$licenses = $licenceMgr.Licenses | where {$_.EditionKey -ne "eval" -and $_.Used -eq 0}
	}elseif($showEval){
		$licenses = $licenceMgr.Licenses | where {$_.EditionKey -eq "eval"}
	}elseif ($LicenseKey -ne $null) {
		if (($LicenseKey.GetType()).Name -eq "String"){
			$licenses = $licenceMgr.Licenses | where {$_.LicenseKey -eq $LicenseKey}
		}else {
			$licenses = $licenceMgr.Licenses | where {$_.LicenseKey -eq $LicenseKey.LicenseKey}
		}
	}
	else {
		$licenses = $licenceMgr.Licenses | where {$_.EditionKey -ne "eval"}
	}
	
	$licenses
}

function Add-vLicense{
<#
.SYNOPSIS
Add New Licenses to the vCenter license manager
 
.DESCRIPTION
Use this function to add licenses  and assing to either the vcenter or the hosts
 
.PARAMETER  xyz 
 	
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-28
#>
param (
	$VMHost ,
	[Parameter(ValueFromPipeline=$True)]$License = $null,
	[string]$LicenseKey = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX",
	[switch]$AddKey
    )
	$LicenseMgr = Get-View -Id 'LicenseManager-LicenseManager'
	$LicenseAssignMgr = Get-View -Id 'LicenseAssignmentManager-LicenseAssignmentManager'
	if($License){
		$LicenseKey = $License.LicenseKey
		$LicenseType = $LicenseMgr.DecodeLicense($LicenseKey)
	}else{
		$LicenseType = $LicenseMgr.DecodeLicense($LicenseKey)
	}
	
	if ($LicenseType) {
		if ($AddKey){
			$LicenseMgr.AddLicense($LicenseKey, $null)
		}else{
			if ($LicenseType.EditionKey -eq "vc"){
				#$servInst = Get-View ServiceInstance
				$Uuid = (Get-View ServiceInstance).Content.About.InstanceUuid
				$licenseAssignMgr.UpdateAssignedLicense($Uuid, $LicenseKey,$null)
			} else {
				$key = Get-vLicense -LicenseKey $LicenseKey
				if($key  -and ($key.Total-$key.Used) -lt (get-vmhost $VMHost | get-view).Hardware.CpuInfo.NumCpuPackages){
					Write-Host "Not Enough licenses left"
				} else{
					$Uuid = (Get-VMhost $VMHost | Get-View).MoRef.Value
					$licenseAssignMgr.UpdateAssignedLicense($Uuid, $LicenseKey,$null)
				}
			}	
		}
	}	
}


function Remove-vLicense{
<#
.SYNOPSIS
Function to remove a licenses that is not in use in vCenter
 
.DESCRIPTION
Use this function to remove a license
 
.PARAMETER  xyz 
 
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-28
#>
param (
	[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$True, HelpMessage="Enter the key or keyobject to remove")]$License
	)
	$LicObj = Get-vLicense $License 
	if($LicObj.Used -eq 0){
		$LicenseMgr = Get-View -Id 'LicenseManager-LicenseManager'
		$LicenseMgr.RemoveLicense($LicObj.LicenseKey)
	}else{
		Write-Host " The license is assigned and cannot be removed"
	}
}

Virtual Machine Snapshots in Win8 Hyper-V massage with PowerShell

In the new win8 there is a function to merge the snapshot taken on a VM without putting it into saved state/turn off. In the Windows 2008 and 2008 R2 there was a big no-no to taking snapshots on production machines, how about now in the new version? Well their replication function uses snapshots so it must be good enough. Then as always you should consider the consequences of taking snapshots and rolling back on different systems as the data in a database may be lost when jumping around.

The Cmdlets that are relevant for Snapshots :

  • Checkpoint-VM
  • Get-VMSnapshot
  • Remove-VMSnapshot
  • Export-VMSnapshot
  • Restore-VMSnapshot
  • Rename-VMSnapshot

If you search among the cmdlets the first CheckPoint-VM is not very easy to find, I am woundering why they(MS) has decided that name?! (I have before complained about checkpoint in SCVMM, maybe it is from there it has the roots)

Here is a PowerShell oneliner that makes 50 Snapshots on a VM (the limit of 50 snapshots is still valid as i tested to make 60 snapshots and got errors from 50+)

for($i=1 ;$i -le 50 ; $i++){Checkpoint-vm -SnapshotName $i -VMName lajs}

Here is the error.

How do I know how many snapshots i have on a VM?

Or if you must, check the GUI..

When I now have 50 snapshots I have to remove one before taking a new, the Remove-VMSnapshot has a parameter -IncludeAllChildSnapshots that is quite handy if you have like me 50 snapshots that you want to remove. I use the Select-Object -First 1 to get the first snapshot so i can remove all at once.

Get-VM lajs | Get-VMSnapshot | Select-Object -First 1 | Remove-VMSnapshot -IncludeAllChildSnapshots

How about the cmdlet Export-VMSnapshot, it cannot be run when the VM is running, but it creates an exported VM that is from the snapshot. This can be very useful if you want to have a machine from a specific snapshot built.

How to go to a snapshot with Restore-VMSnapshot then, when I restore I have to confirm but not when deleting?

If you haven´t found the reference page on technet for WIN 8 Hyper-V powershell cmdlets it is here.

Change SCSI controller with PowerCLI on win 2008 R2 VM from Paravirtual

I found this KB 2004578 and thought that of course should this be done with PowerCLI

I made a function to be able to do it just by sending the VM parameter, it can be done if the VM is already shutdown with a simple one-liner

Get-VM v2vtest2 | Get-ScsiController | where {$_.Type -eq "Paravirtual"} | Set-ScsiController -Type VirtualLsiLogicSAS

But I wanted a more sophistical approach where my function shutdown the VM properly and then change the controller and starts the VM, the tricky part here was to check that the VM actually had shutdown before I change controller 🙂

function Change-ScsiController{
<#
.SYNOPSIS
Stop a VM and replace the SCSI controller and start it again

.DESCRIPTION
Use this function to change scsi cntroller

.PARAMETER  xyz 

.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-21
#>
    param (
   [Parameter(Position=0,Mandatory=$true,HelpMessage="A virtual machine",
    ValueFromPipeline=$True)]
    $VM
    )
	$VM = Get-VM $VM	
	
	Shutdown-VMGuest -VM $VM -Confirm:$false
	while ($VM.PowerState -eq "PoweredOn")
	{
	$VM = Get-VM $VM
	Start-Sleep -s 1	
	}
	Get-ScsiController -VM $VM | where {$_.Type -eq "Paravirtual"} | Set-ScsiController -Type VirtualLsiLogicSAS 
	Start-VM -VM $VM
	
}

Using Windows PowerShell Web access for VMM2012 Administration

Today i had the pleasure to install and configure the Windows PowerShell Web Access in Windows 8. This gives you an opportunity to administer your internal servers with a Web Powershell Console. The really nice part here is that when I have enabled this I can connect to an Windows Server 2008 R2 with Powershell v2.

I have configured it with Authorization to everything, now this is a test environment but in your maybe you should be more restrictive,

Get-WindowsFeature WindowsPowerShellWebAccess | Add-WindowsFeature
Install-PswaWebApplication -UseTestCertificate
Add-PswaAuthorizationRule * * *

So I can connect with for example a Ipad and administer my Hyper-V Cluster in SCVMM2012 😛

In this link you can see how to configure this on your Windows 8 Server Beta.

Here is the login prompt…

And here you can see how i run commands in the console, As you can see I must use Import-Module to import the VMM 2012 cmdlets before I can use them. This is a flash embedded video from youtube (where i uploaded it to) If you do not see it you can go to this link


I still have to find out why I cannot use the PowerCLI PSSnapin, I get an OutOfMemory exception when trying to connect-viserver 🙁 will have to dig a bit deeper to check that one out. Maybe there is a bug in the PSSnapin, an excellent time for VMware to make a Module instead!