Check number of running VMs on datastores

If you are running too many VM´s on your datastores in your vSphere environment you can have some problems, this if your SAN is not VAAI compliant and can handle SCSI locking etc.

Alan Renouf has made a blog post about how to get a report about how many VM´s you have on every datastore, I have extended to only report on running VM´s as these are the interesting number..

Get-Datastore | Select Name, @{N="NumVM";E={@($_ | Get-VM | where {$_.PowerState -eq "PoweredOn"}).Count}} | Sort Name | Export-Csv -Path C:\temp\vms-datastore.csv -NoTypeInformation -UseCulture

And the report loooks like this when imported into excel

Use of PowerCLI and invoke-script to get HAL running of Windows VM´s

I was thinking of how to get an report after reading about the converter best practice from Vladan and he also has this blog post about how to change the HAL, but first i want to know what running guests are there that has the wrong HAL running. I have selected to get an report out of the running windows 2003 ( windows 2008 and later has an uniform HAL that is the same for one or more cpu´s).

I have made an little script somewhat alike to Alan Renouf´s to get the HAL of the VM guest running in your environment, the difference in my approach is that i use invoke-script and get the info from inside the VM, as i have a case where the VMs are isolated and i can not get the wmi info from the network, Arnim Van Lieshout has made one blog post about  running wmi queries this way.


# Check the HAL in the VM with invoke-VMScript
# Niklas Akerlund / RTS

$VMs = Get-VM | Where {$_.Guest.OSFullName -eq "Microsoft Windows Server 2003 Standard (32-bit)" -and $_.PowerState -eq "PoweredOn"}
$guestcred = get-Credential
$report = @()

foreach ($VM in $VMs){
    $HAL = Invoke-VMScript "wmic path Win32_PnPEntity WHERE ""DeviceID='ROOT\\ACPI_HAL\\0000'"" GET NAME /VALUE" -VM $VM -GuestCredential $guestcred -scripttype "bat"
	$HAL = $HAL.Split('=')[1]
    $data = New-Object PSObject -property @{
    $report +=$data

$report | Export-Csv -path c:\temp\hal4.csv -NoTypeInformation -UseCulture

And the simple report looks like this:


Create and destroy Logical Networks with powershell in SCVMM 2012

I am at a customer and setting up an new environment with Hyper-V hosts and SCVMM 2012 RC, we have succesfully created host-vhd and got bare-metal deploy working including HP PSP software and NIC-Teaming configuration. The hosts are deployed with Windows 2008 R2 Datacenter Core SP1 on HP BL460c G7 blades with flexfabric and an EMC SAN delivers the disks.

Now we had to get the network configured, the customer has several VLANs and i have configured the Hyper-V hosts with the HP nic team tool and have two teamed NICs for the VM traffic. To not have to configure one virtual nic/switch for each VLAN i have enabled promiscuous mode.

Now to make it easier we create a bunch of Logical Networks with some powershell in the SCVMM 2012 powershell console, this because setting up 20 networks manually and also associate them on every host in the cluster is kind of boring, cause if i do not associate the logical networks to the hosts VM adapter i can not assign them on the VMs.

So what does the script look like, the help info from SCVMM powershell console and also view script button in the helps allot when trying to find out what i need to make it work. There are some differences in the cmdlets between vmm 2008 r2 and the 2012 rc.

# Create SCVMM virtual networks and associate them with hosts
# Niklas Akerlund /RTS

$VLANs = Import-Csv vlan1.csv -Delimiter ";"
$VMHostGroup = Get-SCVMHostgroup
$VMHosts = Get-SCVMHost
$LogicalNetworks = @()
foreach ($VLAN in $VLANs){
    $LogicalNetwork = New-SCLogicalNetwork -Name $VLAN.Name
    $LogicalNetworks += $LogicalNetwork
    $Network = $VLAN.IPnet + $VLAN.Octet
    $SubnetVlan = New-SCSubnetVLan -Subnet $Network -VLanID $VLAN.VLAN
    New-SCLogicalNetworkDefinition -Name $VLAN.Name -LogicalNetwork $logicalNetwork -VMHostGroup $VMHostGroup -SubnetVLan $SubnetVlan

foreach ($VMHost in $VMHosts){   
    $vmHostNetworkAdapter = Get-SCVMHostNetworkAdapter -Name "VM" -VMHost $VMHost
    foreach ($LogicalNet in $LogicalNetworks){
        Set-SCVMHostNetworkAdapter -VMHostNetworkAdapter $vmHostNetworkAdapter -AddOrSetLogicalNetwork $logicalNet

After running the script it looks like this in the properties on one Logical Network.

After this i also want to be able to remove the Logical Networks (or at least some) when they are not needed anymore, As there are some dependencies we have to remove these first and at last the Logical Network

# Remove Logical Networks from SCVMM2012
# Niklas Åkerlund /RTS

$VLANs = Import-CSV vlan1.csv -Delimiter ";"
$VMHosts = Get-VMHost

foreach ($VLAN in $VLANs){
    $LogicalNetwork = Get-SCLogicalNetwork $VLAN.Name
    if ($LogicalNetwork -ne $null){
        foreach ($VMHost in $VMHosts){
            $VMHostNetworkAdapter = Get-SCVMHostNetworkAdapter -Name "VM" -VMHost $VMHost
            Set-SCVMHostNetworkAdapter -VMHostNetworkAdapter $VMHostNetworkAdapter -RemoveLogicalNetwork $LogicalNetwork
        $LogicalNetworkDefinition = Get-SCLogicalNetworkDefinition -LogicalNetwork $LogicalNetwork 
        Remove-SCLogicalNetworkDefinition -LogicalNetworkDefinition $LogicalNetworkDefinition
        Remove-SCLogicalNetwork -LogicalNetwork $LogicalNetwork

To get some more information about the powershell cmdlets look at this reference site.

PowerCLI update on VM network cards and types report also with MAC´s

Today i added some fields in my little reportscript for the VM and their NICs, the reason was because of a customer that had an issue with duplicate MAC´s on their network.

We had earlier this year moved some VMs from an old vCenter to a new, i have made a blog post about the migration and the script we ran there.

Now when they started to deploy new VMs on the old vCenter it gave out the same MAC addresses as the ones on the VM´s that we had moved.. not so good, there is a fix that can be implemented on the old vCenter so it will start using new MAC´s instead, if you have this issue you can read the following KB 1024025 and set a new ID on the old vCenter and restart the service 🙂

But to check the VMs on both vCenter servers i ran the following script to get the data, the customer wanted both the VM name and the hostname/fqdn from the vm, also for every nic if it was generated or assigned.

# Get the Virtual Network Adapter
# Niklas Akerlund / RTS

$VMs = Get-VM *
$Data = @()

foreach ($VM in $VMs){
 	$VMGuest = Get-View $VM.Id	
	$NICs = $VM.NetworkAdapters
	foreach ($NIC in $NICs) {
		$into = New-Object PSObject
		Add-Member -InputObject $into -MemberType NoteProperty -Name VMname $VM.Name
		Add-Member -InputObject $into -MemberType NoteProperty -Name VMfqdn $VM.Guest.HostName
		Add-Member -InputObject $into -MemberType NoteProperty -Name NICtype $NIC.Type
		Add-Member -InputObject $into -MemberType NoteProperty -Name MacAddress $NIC.MacAddress
		Add-Member -InputObject $into -MemberType NoteProperty -Name AddresType $NIC.ExtensionData.AddressType
		$Data += $into

$Data | Export-Csv -Path c:\powercli\VMNICinfo.csv -NoTypeInformation

Matt Boren that has the site helped me with an more efficient way of getting the data, my script took about 5-10 minutes and Matt´s took 30 seconds, his key to lower time is using the Get-View for everything (i was only using it to get the vm.guest.hostname)

&{Get-View -ViewType VirtualMachine -Property Name, Guest.HostName, Config.Hardware.Device | %{
    $viewThisVM = $_
    $viewThisVM.Config.Hardware.Device | ?{$_ -is [VMware.Vim.VirtualEthernetCard]} | %{
        New-Object -Type PSObject -Property @{
            VMname = $viewThisVM.Name
            VMfqdn = $viewThisVM.Guest.HostName
            NICtype = $_.GetType().Name
            MacAddress = $_.MacAddress
            AddressType = $_.AddressType
        } ## end new-object
    } ## end foreach-object
} ## end foreach-object
} | Select VMname,VMfqdn,NICtype,MacAddress,AddressType | Export-Csv -Path C:\VMNICinfo2.csv -NoTypeInformation -UseCulture

And the result when imported into excel looks something like this:


Virtual Machine VMDK file report with PowerCLI

I have created a simple report-script that gives a list of what kind of format and how many vmdk each VM has. The report tells me if the disks are Thin or Thick and what size they are i GB.

after some magic in Excel it looks like this 🙂

And the powerCLI script looks like this, it is quite simple but still gives me information that i need for all my VMs on all datastores and quickly i can tell which machines that uses a lot of disk on my precious SAN 😉


# Get data about vmdk and format
# Niklas Åkerlund / RTS

$VMs = Get-VM *
$Data = @()

 foreach ($VM in $VMs){
	$VMDKs = $VM | get-HardDisk
	foreach ($VMDK in $VMDKs) {
		if ($VMDK -ne $null){
			$CapacityGB = $VMDK.CapacityKB/1024/1024
			$CapacityGB = [int]$CapacityGB
			$into = New-Object PSObject
			Add-Member -InputObject $into -MemberType NoteProperty -Name VMname $VM.Name
			Add-Member -InputObject $into -MemberType NoteProperty -Name Datastore $VMDK.FileName.Split(']')[0].TrimStart('[')
			Add-Member -InputObject $into -MemberType NoteProperty -Name VMDK $VMDK.FileName.Split(']')[1].TrimStart('[')
			Add-Member -InputObject $into -MemberType NoteProperty -Name StorageFormat $VMDK.StorageFormat
			Add-Member -InputObject $into -MemberType NoteProperty -Name CapacityGB $CapacityGB
			$Data += $into

$Data | Sort-Object VMname,Datastore,VMDK | Export-Csv -Path C:\temp\VM-VMDKs.csv -NoTypeInformation