Upgrading my Windows 2012 RC to RTM with Hyper-V VM´s on

Well the Windows 2012 Launch site is probably a bit overloaded.

Anyway, I have downloaded my iso from the technet plus account and now I will start installing.

Here have Olav made a post about how to upgrade from RC to RTM and it is probably not supported but I tried it anyway.

To download the Windows 2012 you just go to technet and chose the evaluation

When it is downloaded I edit the cversion.ini to 8400 and then start the installation,

I like that the core version is default when starting the installation

And now as you can see I can choose the upgrade option

And lookilooki, I can now upgrade with no complaints, or at least just warnings

 And after quite a bit of waiting and reboots the server is actually upgraded and now I have started my VM´s again (yes with Powershell :-P)

Using PowerShell to get/start VM´s from Hyper-V servers in Active Directory

Of course I would rather have all my hosts in my System Center VMM 2012 SP1 but if I do not, or I just as an ITPro admin want to check if there are some new Hyper-V servers out there in my Active Directory and if they have VM´s on them I can use PowerShell.

I have looked at Ravikanth´s blog and done some modifications, also I am using the Win2012 and Powershell v3.

I can with the following powershell cmd get all hyper-v virtual machines in my Active Directory (of some reason the VMware machines do not get registered in the AD as virtual machines). With powershell version 3 it autoloads the Active Directory Module, this requires though that I have the feature RSAT-AD-PowerShell installed, easily done with Get-WindowsFeature RSAT-AD-PowerShell | Add-WindowsFeature.

Get-ADObject -Filter 'Name -like "*Virtual*"' | %{$_.DistinguishedName.Split(",")[1].replace("CN=","") }

I cannot do so much more with this information, what I want is to check a list of Hyper-V servers and also try to get the VM´s on them, sadly only win2012 servers can interact with the hyper-v powershell module and give that info, but hey whom has win 2008 r2 hyper-v servers 😉

This first query gives me all Hyper-V servers in the domain, 2008->2012

Get-ADObject -Filter 'Name -like "*Hyper-V"' | %{$_.DistinguishedName.Split(",")[1].replace("CN=","") }

This next query uses that info and asks the Hyper-V servers for their VM´s

Get-ADObject -Filter 'Name -like "*Hyper-V"' | %{$_.DistinguishedName.Split(",")[1].replace("CN=","") } | %{get-vm -ComputerName $_ -ErrorAction SilentlyContinue} | ft ComputerName,Name,State,Uptime -AutoSize

I can also use this to do things with the VM´s, like starting or stopping, observe that i just want to start the VM´s that start with the name test*.

Get-ADObject -Filter 'Name -like "*Hyper-V"' | %{$_.DistinguishedName.Split(",")[1].replace("CN=","") } | %{get-vm test* -ComputerName $_ -ErrorAction SilentlyContinue} | Start-VM

At last now I am officially an MCSE:Private Cloud

At the MMS 2012 I had the opportunity to write the beta exam 71-246, Monitoring and Operating a Private Cloud with System Center 2012. This exam was released during the summer as 70-246

As my earlier post announced I could see on the Prometric site that I passed, but the MCP site did not reflect this and I waited quite a while but nothing happend, so I sent in a support request and now after a week I got a mail that they have solved the transfer from Prometric.

Here is a screendump of my certification transcript 🙂 and watch the date of achievement..

 

Good luck you other guys in achieving MCSE Private Cloud!

New free tool vOPS Server Explorer 5.1 from vKernel

There is a new version of the vKernel Server Explorer that has a Environment Explorer view, this can handle multiple hypervisors (current support is Hyper-V, VMware vSphere and RHEV). The tool gives you as an administrator or consultant the insight in the environment and can give you answers if there are some issues and if you are running out of capacity.

The software is packed as an OVF and imported into your vSphere environment, as the vOPS server Readme text file describes there will also be an Hyper-V appliance that will be importable into an Hyper-V host and that with an collector for Hyper-V, do not know when that will be released though.

I have imported it with PowerCLI and then edited the vCPU to 2 instead of 4 and memory to 4 GB instead of 8 because my lab machines has limited resourses, It is really easy to deploy as you can see.

After import and configure I start it and then use a browser to the IP adress and configure, with this current version I can only add vSphere vCenter and RHEV

To add a vCenter I have to set the vCenter statistic level to at least 2 on all intervals

When that is done I successfully add the vCenter to the Server Explorer

With this you get three free tools in one, Environment Explorer, vScope Explorer and SearchMyVM Explorer that all can help you get the initial info you need. and If you want you can activate a free vOPS trial to extend the functionality.

In my small test/lab environment it looks like this

Download the Server Explorer and test yourself -> vOPS Server Explorer 5.1

Using PowerCLI to set CPU/Memory reservation on VM´s in vSphere

I have made a function to set reservations on VM´s in PowerCLI. The function takes a VM as parameter and also percentage of CPU and Memory you want to reserve.

The function checks the Mhz of the physical CPU from the Host the VM is running on and makes the reservation from this.

In the function I can set both memory and cpu reservation or just one of them

here is a screendump of the function being used

and here is the PowerCLI

function Set-VMReservation{
<#
.SYNOPSIS
Set VM Reservation on Memory and/or CPU

.DESCRIPTION
Use this function set VM reservations 

.PARAMETER MemoryMB
Use this parameter to set the percent of memory reserved for the VM

.PARAMETER CpuMhz
Use this parameter to set the percent of CPU Mhz from the host CPU to be reserved

.NOTES
Author: Niklas Akerlund
Date: 2012-07-19
#>
    param (
   [Parameter(Position=0,Mandatory=$true,HelpMessage="A VM",
    ValueFromPipeline=$True)]
    $VM,
	$MemoryMB = 0,
	$CpuMhz = 0
    )
	$VM = Get-VM $VM
	if ($MemoryMB -ne 0 -and $CpuMhz -ne 0){
		$MemoryMB = $MemoryMB/100
		[int]$MemoryMB = $VM.MemoryMB*$MemoryMB
		$CpuMhz = $CpuMhz/100
		[int]$CpuMhz = ([math]::truncate(((Get-VMHost -id $VM.extensiondata.summary.runtime.host).ExtensionData.Hardware.CpuInfo.hz)/1000000))*$VM.NumCpu*$CpuMhz
		$VM | Get-VMResourceConfiguration |Set-VMResourceConfiguration -CpuReservationMhz $CpuMhz -MemReservationMB $MemoryMB
	}elseif ($MemoryMB -ne 0 -and $CpuMhz -eq 0){
		$MemoryMB = $MemoryMB/100
		[int]$MemoryMB = $VM.MemoryMB*$MemoryMB
		$VM | Get-VMResourceConfiguration |Set-VMResourceConfiguration -MemReservationMB $MemoryMB
	}elseif ($MemoryMB -eq 0 -and $CpuMhz -ne 0){
		$CpuMhz = $CpuMhz/100
		[int]$CpuMhz = ([math]::truncate(((Get-VMHost -id $VM.extensiondata.summary.runtime.host).ExtensionData.Hardware.CpuInfo.hz)/1000000))*$VM.NumCpu*$CpuMhz
		$VM | Get-VMResourceConfiguration |Set-VMResourceConfiguration -CpuReservationMhz $CpuMhz
	}elseif ($MemoryMB -eq 0 -and $CpuMhz -eq 0){
		$VM | Get-VMResourceConfiguration |Set-VMResourceConfiguration -CpuReservationMhz 0 -MemReservationMB 0
	}
}

In this example I have set the CPU reservation to 60 % and Memory to 40 %

vSphere Cluster Host-VM rule affinity with PowerCLI

A colleague wanted a script that could make a Host-VM affinity rule so that certain VM´s that resided on one storage at one site would run on the hosts on that site, the cluster spanns over two sites so the VM´s can run at both sites but one datastore is primary at the first site and the other at the second site.  So He wanted to get the VM´s that have their storage on datastoreLocation1 to be in an host-vm affinity rule “Should Run” on the hosts that is in that site. In this community post I found most of the code, I made som adjustments but mostly the cred goes to @lucd22 and GotMoo.

Here you can see the screendump from the cluster settings

Here is the powerCLI that has been run

One thing here was also that this VMgroup should be updated once a day if there was new VM´s that needed to be included. So this lines should be run in a scheduled task, this will make the DRSVMGroup VMLocationDC1 to be updated with the VM´s currently located at that datastore:

$VM = get-datastore delad02 | get-vm
Update-DrsVMGroup -cluster vmw* -VMs $VM -groupVMName VMLocationDC1

Here are the PowerCLI functions for doing this. As you can see I have an switch parameter for -MustRun, that will create the rule as a Must Run on these hosts.

function New-DRSGroupRule{
<#
.SYNOPSIS
Create a new DRSGroupRule for VMs to reside on some hosts in a cluster

.DESCRIPTION
Use this function to create vms in a group and hosts in a group and a host-vm affinity

.PARAMETER  MustRun
A switch that will create the rule with Must Run on these host, if not set it will create the rule with should run.

.NOTES
Author: Niklas Akerlund / RTS (most of the code came from http://communities.vmware.com/message/1667279 @LucD22 and GotMoo)
Date: 2012-06-28
#>
	param (
	[Parameter(Position=0,Mandatory=$true,HelpMessage="A Cluster",
	ValueFromPipeline=$True)]
	$cluster,
	$VMHosts,
	$VMs,
	[string]$Name,
	[switch]$MustRun
	)
	
	$cluster = Get-Cluster $cluster

	$spec = New-Object VMware.Vim.ClusterConfigSpecEx
	$groupVM = New-Object VMware.Vim.ClusterGroupSpec 
	$groupVM.operation = "add" 
	$groupVM.Info = New-Object VMware.Vim.ClusterVmGroup
	$groupVM.Info.Name = "VM$Name"

	Get-VM $VMs | %{
	$groupVM.Info.VM += $_.Extensiondata.MoRef
	}
	$spec.GroupSpec += $groupVM

	$groupESX = New-Object VMware.Vim.ClusterGroupSpec 
	$groupESX.operation = "add"
	$groupESX.Info = New-Object VMware.Vim.ClusterHostGroup
	$groupESX.Info.Name = "Host$Name"

	Get-VMHost $VMHosts | %{
	$groupESX.Info.Host += $_.Extensiondata.MoRef
	}
	$spec.GroupSpec += $groupESX

	$rule = New-Object VMware.Vim.ClusterRuleSpec
	$rule.operation = "add"
	$rule.info = New-Object VMware.Vim.ClusterVmHostRuleInfo
	$rule.info.enabled = $true
	$rule.info.name = $Name
	if($MustRun){
		$rule.info.mandatory = $true
	}else{
		$rule.info.mandatory = $false
	}
	$rule.info.vmGroupName = "VM$Name"
	$rule.info.affineHostGroupName = "Host$Name"
	$spec.RulesSpec += $rule

	$cluster.ExtensionData.ReconfigureComputeResource($spec,$true)
}

function Update-DrsVMGroup {
<#
.SYNOPSIS
Update DRS VM group with a new collection of VM´s

.DESCRIPTION
Use this function to update the ClusterVMgroup with VMs that are sent in by parameters

.PARAMETER  xyz 

.NOTES
Author: Niklas Akerlund / RTS (most of the code came from http://communities.vmware.com/message/1667279 @LucD22 and GotMoo)
Date: 2012-06-28
#>
	param (
	$cluster,
	$VMs,
	$groupVMName)
	
    $cluster = Get-Cluster $cluster
    $spec = New-Object VMware.Vim.ClusterConfigSpecEx
    $groupVM = New-Object VMware.Vim.ClusterGroupSpec 
    #Operation edit will replace the contents of the GroupVMName with the new contents seleced below.
    $groupVM.operation = "edit" 

    $groupVM.Info = New-Object VMware.Vim.ClusterVmGroup
    $groupVM.Info.Name = $groupVMName 

    Get-VM $VMs | %{
        $groupVM.Info.VM += $_.Extensiondata.MoRef
    }
    $spec.GroupSpec += $groupVM

    #Apply the settings to the cluster
    $cluster.ExtensionData.ReconfigureComputeResource($spec,$true)
}

When I get the time I might add some more functionality to also remove rules and groups.

VM affinity when using vCloud Director and vApps

I made a blog post some time ago, where i created a powerCLI function for creating a VM affinity rule that would keep my VM´s in a vApp together in the cluster for better VM-VM performance. I then checked for MoRef to get the VM correlated between vCloud Director and vCenter.

The answer to my problem was much closer than I thought, the vCloud director creates a folder in the “VM´s and Template view” for each vApp and guess what, all VM´s are in there.. so I do not need to ask the vCloud Director anymore (well if I want the Cloud vApp name I do need to ask it..) but ironically I had not looked there and found out that the folders actually where created for each deployed vCloud vApp :-/

So the code is a bit simpler and to get all VM´s from a folder I just type this, the asterisk is because the folder also gets a unique id

Get-Folder | where {$_.Name -like "ProdvCPod*"} | Get-VM

And then I just need to put those VM´s into an array and create a DRS rule, and here is the function that does this

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

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

	if ($CIVApp -ne " " -or $CIVApp -ne $null -or $CIVApp.length -ne 0 ){
		$Cluster = Get-Cluster $Cluster
		$VAppname = $CIVApp + "*"
		$VMs =  Get-Folder | where {$_.Name -like $VAppname} | Get-VM	
		
		if (!(Get-DrsRule -Cluster $Cluster -Name $CIVApp -ErrorAction SilentlyContinue)){ 
			New-DrsRule -Name $CIVApp -Cluster $Cluster -KeepTogether $true -VM $VMs
		}else{
			Remove-DrsRule -Rule (Get-DrsRule -Cluster $Cluster -Name $CIVApp) -Confirm:$false
			New-DrsRule -Name $CIVApp -Cluster $Cluster -KeepTogether $true -VM $VMs
		}
	}
}

To run it:

and it looks something like this if I check the cluster settings

preferably you have set your DRS cluster to fully automated or not so much will happen 🙂

Clone VM on Win 2012 Hyper-V v3 when it is running using Powershell

I wanted to create a function that could help an IT Pro Admin with the task to create a clone of a running VM, Yes you can use the Export-VM cmdlet but then your VM must be turned off and in some cases, for example when you want to test a new release or patch on a production system but first test it in a safe environment and you are not allowed to stop the original VM.

The function exists in System Center Virtual Machine Manager but there it also must be turned off

So how do I do? I have made a PowerShell function that take a snapshot, copies the vhd files and creates a new VM, connect the vhd´s and network cards, configures the VM with number of processors, dynamic memory etc.

As the Snapshot merges the vhdx files when the VM is running in this new Hyper-V version I thought it was an sufficient way to solve that the VM actually was not writing to the .vhdx files when I copy them but into the .avhdx diff file.

This is a version 0.1 and yes it need some development but right now I do not have the time to make it supernice,

Here you can see it in action

And when It is finished It looks like this in the gui

And here is the PowerShell function

<#
.Synopsis
   Function to clone a running VM
.DESCRIPTION
   This function can be used to clone a running vm and connect the copied vhd´s and network
.EXAMPLE
   Clone-VM -VMName vmdisktest -VMCloneName vmdisktest-clone -Path c:\VMs
.EXAMPLE
   Clone-VM -VMName vmdisktest -VMCloneName vmdisktest-clone -Path c:\VMs -Switch Private
.Notes
Author: Niklas Akerlund
Date: 2012-06-19
#>
function Clone-VM
{
    [CmdletBinding()]
    [OutputType([int])]
    Param
    (
        # Name of the VM to be cloned
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $VMName,
        [string] $VMCloneName,
        # Where to store the VM-clone 
        [string] $Path,
        # Set to another network switch
        [string] $Switch = " "    
    )

    # Get VM
    $VM = Get-VM $VMName
    $VHDs = Get-VMHardDiskDrive -VM $VM
    #$VHDPath = (Get-VMHardDiskDrive -VM $VM).Path
    $VHDClonePath = "$Path\$VMCloneName\Virtual Hard Disks\"
    
    # Create a new array of VHD info
    $VHDOrg = @()
    foreach ($VHD in $VHDs){
        $data = New-Object PSObject -property @{
            VHDName = (Get-Item $VHD.Path).Name
            VHDPath = $VHD.Path
            ControllerType = $VHD.ControllerType
            ControllerNumber = $VHD.ControllerNumber
            ControllerLocation = $VHD.ControllerLocation

        }
        $VHDOrg +=$data
    }

    $VMNics = Get-VMNetworkAdapter -VM $VM

    # Take snapshot 
    $VM | Checkpoint-VM 

    New-Item -ItemType directory -Path $VHDClonePath

    New-VM -Name $VMCloneName -Path $Path -NoVHD -MemoryStartupBytes $VM.MemoryStartup -BootDevice IDE
    $VMClone = Get-VM -Name $VMCloneName
    Get-VMNetworkAdapter -VMName $VMCloneName | Remove-VMNetworkAdapter
   
    # Configure VM-Clon
    if ($VM.DynamicMemoryEnabled){
        Set-VM -VMName $VMCloneName -ProcessorCount $VM.ProcessorCount -DynamicMemory -MemoryMinimumBytes $VM.MemoryMinimum -MemoryMaximumBytes $VM.MemoryMaximum
    }else{
        Set-VM -VMName $VMCloneName -ProcessorCount $VM.ProcessorCount -StaticMemory
    }

    # Add all network cards
    foreach ($VMNic in $VMNics){
        if ($Switch -eq " "){
            Add-VMNetworkAdapter -VMName $VMCloneName -SwitchName $VMNic.SwitchName -IsLegacy $VMNic.IsLegacy
        }else{
            Add-VMNetworkAdapter -VMName $VMCloneName -SwitchName $Switch -IsLegacy $VMNic.IsLegacy
        }
    }

    # Copy all VHDs
    foreach ($VHDcopy in $VHDOrg){
        
        $Dest = $VHDClonePath + $VHDcopy.VHDName
        Copy-Item -Path $VHDcopy.VHDPath -Destination $Dest
        Add-VMHardDiskDrive -VMName $VMCloneName -ControllerType $VHDCopy.ControllerType -ControllerLocation $VHDCopy.ControllerLocation  -ControllerNumber $VHDCopy.ControllerNumber -Path $Dest   
    }

    # Remove snapshot 
    $VM | Remove-VMSnapshot

}

Good luck in testing, but do take in consideration that this is an copy of the running VM so do not start it at the same time on the same network or you will get IP collision etc, as you can see above I have added an -Switch parameter that you can use to set the network cards of the VM to be connected on another switch to avoid any problems.. 🙂

Using Powershell v3 scheduling for off hours Hyper-V VM maintenance/configuring

A colleague wanted a script for a reconfiguration of a VM´s settings. Once the VM is powered off that is not a big issue. The smart thing is when using Powershell version 3 I can configure a scheduled job that I want to execute off hours.

Imagine that you have the task to add a vCPU to a VM but you can only do it during the service window that happens to be around midnight, I don´t know about you but I rather sleep then if I can automate it. Yes I could in earlier versions use scheduled task but now I am using Win 2012 and Hyper-V 3 and the latest powershell.

So what do I need to do then, Jan Egil Ring has made a blog post about scheduled jobs and I want to show an example regarding Virtual Machine management..

In Powershell version 3 there are 16 cmdlets regarding scheduled jobs

First I need a Trigger

$once = New-JobTrigger -Once -At 11:59PM

Then I need a job with the trigger, I could use a parameter -FilePath to use a script file instead of -ScriptBlock

Register-ScheduledJob -ScriptBlock {$vm = Get-VM TestVM2 ; Stop-VM -VM $vm ; Set-VM -VM $vm -ProcessorCount 2 ; Start-VM -VM $vm} -Trigger $once

And then just wait or sleep 😛

And here you can see a screendump of the changing, Now I changed the trigger time to not have to wait to midnight for the blog post but I think you can imagine…

To check that the Job went ok, you run the cmdlet Get-Job ( and if you do not get any job you might need to run import-module PSScheduledJob to get the right Get-Job in that session)

God luck in scheduling your VM tasks 🙂

I passed the 71-246 at MMS 2012 -> MCSE: Private Cloud

As the buzz around twitter said that their result was showing I checked yesterday but on the Prometric site it just said “Tested”. When I woke up today I had to check again and now it looked better 🙂

As you can see I took the test at 4:30 PM on the first day of MMS 2012 so this means I am one of the first passing 🙂 , until someone else claims an earlier time I will say that I am the first MCSE : Private Cloud in Sweden 🙂

This as the requirement is MCSA and that I can count my 70-659 towards this certification 🙂

Good luck in testing!