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"
	}
}

Update vSphere 5 hosts to U1 with Update manager and PowerCLI

Today I wanted to update my lab environment hosts to U1 of vSphere 5, of course with PowerCLI, there is no other way or is it?

This reference indicates there is not so many cmdlets but is it enough? Yes it is!

As the PowerCLI installation does not include the VUM cmdlets i had to download and install them

I have already upgraded my vCenter and VUM to U1, this as it is always a best practice to first update the vCenter and then the hosts

the following script do the whole process of both making a Patch baseline and attaching it to the cluster and then Scan/Remidate (now i only have two hosts but this is quite powerfull if i have lots of more). The script allows some parameters, for example if you already have a baseline you can use that and attach/remediate your cluster, or you want another patch in the baseline.

<#
 .SYNOPSIS
 Upgrade ESXi Hosts to an Update Version 

 .DESCRIPTION
 Create an baseline and upgrade a Cluster to an vSphere 5 update with Update Manager, If you already have a baseline just use the BaseName parameter

 .Author
 Niklas Akerlund /RTS 2012-03-23 (original script from Jonathan Medd)

 .PARAMETER  Cluster
 The name of the host to upgrade.

 .PARAMETER  PatchName
 Enter the name of the Patch/Update
 
 .PARAMETER Name
 Enter the name of the vCenter server to connect to

 .EXAMPLE
 PS C:\> Update-HostsU1.ps1 -Cluster VMWCL
#>
#requires -pssnapin VMware.VimAutomation.Core
#requires -pssnapin VMware.VumAutomation

[CmdletBinding()]
param(
 [Parameter(Position=0, Mandatory=$true, HelpMessage="Enter the name of Cluster")]
 $Cluster,
 [Parameter(HelpMessage="Enter the name of the patch")]
 [String]
 $PatchName = "VMware ESXi 5.0 Complete Update 1",
 [Parameter(HelpMessage="Enter the baseline name")]
 [String]
 $BaseName = "vSphere ESXi 5 U1"
 )

process{

	# Create a baseline to use
	if(!(Get-Baseline -Name $BaseName -EA 0)){
		# Get the update and add a Patchbaseline
		$Patch = get-patch | where {$_.Name -eq $PatchName}
		New-PatchBaseline -Name $BaseName -Static -IncludePatch $Patch
	}
	# Attach the baseline on the cluster
	$Cluster = Get-Cluster $Cluster
	$Baseline = Get-Baseline -Name $BaseName
	if($Baseline){
		$Baseline | Attach-Baseline -Entity $Cluster
		
		# Scan the Cluster 
		$Cluster | Scan-Inventory
		
		# Remediate the cluster with the baseline
		$Cluster | Remediate-Inventory -Baseline $Baseline -ClusterDisableDistributedPowerManagement:$true -ClusterDisableFaultTolerance:$true -ClusterDisableHighAvailability:$true -Confirm:$false -HostDisableMediaDevices:$true
		
	}
}

And here are some screenshots of it running,

One host successfully updated and the remediate migrates the VM´s and start with the other host.

Finally the hosts in the cluster are updated.

I have used some of the code from Jonathan Medd´s post on upgrading from 4.0->4.1 to create my script.

 

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
	
}

Updated VMware vSphere FT (Fault Tolerance) function for PowerCLI

After this week when i have been co-teaching a VMware vSphere ICM course i was going to show the students FT and I was seeking in the powerCLI reference for some cmdlets but could not find any.

I created my own function for enabling this, i got inspiration from Cody Bunch post but extended it with a function and also with my function you can disable/enable/remove and test restart/failover the secondary vm. I also check if the FT is enabled or not before making any changes.

Here is the PowerCLI function, i am using some Get-View to be able to use the FT functions.

Updated: Today (Monday 27/2) i added functionality with a possibility to also send VMHost as argument, but then i realized some errors occuring, my assumtions that the primary VM always was the first object when doing a Get-VM was false, i have corrected the function that it actually checks for the correct VM, Primary or Secondary. If you do not send VMHost parameter the FT process will choose a Host for you, this cannot be the same as the Primary VM resides on.

function Set-VMFaultTolerance{
<#
.SYNOPSIS
Enable FT for the VM sent as parameter

.DESCRIPTION
Use this function to enable or disable Fault Tolerance

.PARAMETER  xyz 

.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-02-27
#>
    param (
   [Parameter(Position=0,Mandatory=$true,HelpMessage="A virtual machine",
    ValueFromPipeline=$True)]
    $VM,
	$VMHost = $null,
	[switch]$enableFT,
	[switch]$disableSecondaryFT,
	[switch]$removeFT,
	[switch]$failOverFT,
	[switch]$restartSecondaryFT
    )
	if ($VM.ExtensionData.Config.FtInfo -ne $null){
		$VM = Get-VM $VM | where {$_.Extensiondata.Config.FtInfo.Role -eq 1}
	} else {
		$VM = Get-VM $VM
	}
	if ($VMHost -ne $null){
		$VMHost = Get-VMHost $VMHost | Get-View
		if ($VMHost -ne $null) {
			$VMHostobj = New-Object VMware.Vim.ManagedObjectReference
			$VMHostobj.type = "HostSystem"
			$VMHostobj.value = $VMHost.MoRef.Value
			$VMHost = $VMHostobj
		}
	}

	if ($enableFT) {
		if ($VM.ExtensionData.Config.FtInfo -eq $null){
			$VMview = $VM | Get-View
			$VMview.CreateSecondaryVM($VMHost)
		} else{
			$VMsec = Get-VM $VM.Name | where {$_.Extensiondata.Config.FtInfo.Role -eq 2}| Get-View
			$VMobj = New-Object VMware.Vim.ManagedObjectReference
			$VMobj.type = "VirtualMachine"
			$VMobj.value = $VMsec.MoRef.Value
			$VMview = $VM | Get-View
			$VMview.EnableSecondaryVM($VMobj, $null)
		}
	}elseif ($disableSecondaryFT) {
		if ($VM.ExtensionData.Config.FtInfo -ne $null){
			$VMsec = Get-VM $VM.Name | where {$_.Extensiondata.Config.FtInfo.Role -eq 2 -and $_.PowerState -eq "PoweredOn"}| Get-View
			if ($VMsec -ne $null){			
				$VMobj = New-Object VMware.Vim.ManagedObjectReference
				$VMobj.type = "VirtualMachine"
				$VMobj.value = $VMsec.MoRef.Value
				$VMview = $VM | Get-View
				$VMview.DisableSecondaryVM($VMobj)
			}else {
				Write-Host "The Secondary is already disabled"
			}
		}else {
			Write-Host "This VM is not FT enabled"
		}
	}elseif ($failOverFT) {
		if ($VM.ExtensionData.Config.FtInfo -ne $null){
			$VMsec = Get-VM $VM.Name | where {$_.Extensiondata.Config.FtInfo.Role -eq 2 -and $_.PowerState -eq "PoweredOn"}| Get-View
			if ($VMsec -ne $null){
				$VMobj = New-Object VMware.Vim.ManagedObjectReference
				$VMobj.type = "VirtualMachine"
				$VMobj.value = $VMsec.MoRef.Value
				$VMview = $VM | Get-View
				$VMview.MakePrimaryVM($VMobj)
			}else {
				Write-Host "The Secondary is disabled"
			}
		}else {
			Write-Host "This VM is not FT enabled"
		}
	}elseif ($restartSecondaryFT) {
		if ($VM.ExtensionData.Config.FtInfo -ne $null){
			$VMsec = Get-VM $VM.Name | where {$_.Extensiondata.Config.FtInfo.Role -eq 2 -and $_.PowerState -eq "PoweredOn"}| Get-View
			if ($VMsec -ne $null){
				$VMobj = New-Object VMware.Vim.ManagedObjectReference
				$VMobj.type = "VirtualMachine"
				$VMobj.value = $VMsec.MoRef.Value
				$VMview = $VM | Get-View
				$VMview.TerminateFaultTolerantVM($VMobj)
			}else {
				Write-Host "The Secondary is disabled"
			}
		}else {
			Write-Host "This VM is not FT enabled"
		}
	}elseif ($removeFT){
		if ($VM.ExtensionData.Config.FtInfo -ne $null){
			$VMview = Get-VM $VM | where {$_.Extensiondata.Config.FtInfo.Role -eq 1}| Get-View
			$VMview.TurnOffFaultToleranceForVM()
		} else {
			Write-Host "This VM is not FT enabled"
		}
	} 

}

 

Updated powerCLI function for setting HA Admission control policy in percent with number of hosts

I got the question from a colleague if i could add a parameter in my function, no problem, just some dividing..

So you can either set percent CPU/Memory or number of hosts and from that get a percent on the policy. I have not taken care of the case if you have more than 100 hosts in your cluster (as this is not possible, at least not yet 😉 )

function Set-HAAdmissionControlPolicy{
<#
.SYNOPSIS
Set the Percentage HA Admission Control Policy
 
.DESCRIPTION
Percentage of cluster resources reserved as failover spare capacity
 
.PARAMETER  Cluster
The Cluster object that is going to be configurered 

.PARAMETER numberHosts
When this parameter is set the percentage is set based on number of hosts in cluster
 
.PARAMETER percentCPU
The percent reservation of CPU Cluster resources
 
.PARAMETER percentMem
The percent reservation of Memory Cluster resources
 
.EXAMPLE
PS C:\> Set-HAAdmissionControlPolicy -Cluster $CL -percentCPU 50 -percentMem 50
 
.EXAMPLE
PS C:\> Get-Cluster | Set-HAAdmissionControlPolicy -percentCPU 50 -percentMem 50

.EXAMPLE
PS C:\> Set-HAAdmissionControlPolicy -Cluster $CL -numberHosts 5
 
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-01-25
#>
   param (
   [Parameter(Position=0,Mandatory=$true,HelpMessage="This need to be a clusterobject",
    ValueFromPipeline=$True)]
    $Cluster,
	[int]$numberHosts = 0,
    [int]$percentCPU = 25,
    [int]$percentMem = 25
    )
 
    if(Get-Cluster $Cluster){
 
        $spec = New-Object VMware.Vim.ClusterConfigSpecEx
        $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
        $spec.dasConfig.admissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
		if($numberHosts -eq 0){
        	$spec.dasConfig.admissionControlPolicy.cpuFailoverResourcesPercent = $percentCPU
        	$spec.dasConfig.admissionControlPolicy.memoryFailoverResourcesPercent = $percentMem
 		}else{
			$spec.dasConfig.admissionControlPolicy.cpuFailoverResourcesPercent = 100/$numberHosts
        	$spec.dasConfig.admissionControlPolicy.memoryFailoverResourcesPercent = 100/$numberHosts
		}
        $Cluster = Get-View $Cluster
        $Cluster.ReconfigureComputeResource_Task($spec, $true)
    }
}

powerCLI function to set HA Admission Control Policy in percent

I am attending a VMware vSphere ICM 5 course this week, this because I am planning to become a VCI.

As I am a bit of PowerCLI fan i am trying to do all the labs in the course from the powerCLI console 🙂

In the HA laboration i found that the default implementation of the powerCLI does not allow you to set the HA Admission Control Policy Percentage, only the Host failure the cluster tolerates, here is a link to the powerCLI reference page for Set-Cluster. In the slides VMware recommends that you set percentage in a HA setup.

This led me to develop a powerCLI function that can configure this. The function has a default value for CPU and Memory that is 25 %, so if you only give the Cluster parameter the Capacity setting will be 25 %.

function Set-HAAdmissionControlPolicy{
<#
.SYNOPSIS
Set the Percentage HA Admission Control Policy

.DESCRIPTION
Percentage of cluster resources reserved as failover spare capacity

.PARAMETER  Cluster
The Cluster object that is going to be configurered 

.PARAMETER percentCPU
The percent reservation of CPU Cluster resources

.PARAMETER percentMem
The percent reservation of Memory Cluster resources

.EXAMPLE
PS C:\> Set-HAAdmissionControlPolicy -Cluster $CL -percentCPU 50 -percentMem 50

.EXAMPLE
PS C:\> Get-Cluster | Set-HAAdmissionControlPolicy -percentCPU 50 -percentMem 50

.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-01-19
#>
   param (
   [Parameter(Position=0,Mandatory=$true,HelpMessage="This need to be a clusterobject",
    ValueFromPipeline=$True)]
    $Cluster,
    [int]$percentCPU = 25,
    [int]$percentMem = 25
    )
    
    if(Get-Cluster $Cluster){
    
        $spec = New-Object VMware.Vim.ClusterConfigSpecEx
        $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
        $spec.dasConfig.admissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
        $spec.dasConfig.admissionControlPolicy.cpuFailoverResourcesPercent = $percentCPU
        $spec.dasConfig.admissionControlPolicy.memoryFailoverResourcesPercent = $percentMem
    
        $Cluster = Get-View $Cluster
        $Cluster.ReconfigureComputeResource_Task($spec, $true)
    }
}

Here is a screenshot when running the function

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 @{
        VMName=$VM.Name
        vCPUs=$VM.NumCPU
        HAL=$HAL.Trim('')
    }
    $report +=$data
}

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

And the simple report looks like this:

 

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 vnugglets.com 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:

 

Move VMs from an old SAN to an new using powerCLI part 2

Hi

I was informed that my script in the last post was not enough because @pfuhli has a bit more complex environment and then the Move-VM cmdlet is not sufficient because it moves the whole vm to the new datastore, no matter if the vmdk´s where located on different before.

As in some cases you have an virtual platform with different datastores for different performance levels and one VM has it´s vmdk configured to get the best throughput. So i  did this with help from a script that Luc Dekens did in a communities post, mine added some functionality as his only moved the config file.

please comment if you find something crazy, I have now started to get the hang of why I would use functions :-), yes i should add some error-checking, that will be in version 0.3

Probably it would take some time to get through 500 VM´s but instead of manual work it is worth it.

# Move VMs with sVMotion where vmdk is on different datastores and
# lastly move the config file to the same datastore as hard disk 1
#
# Niklas Åkerlund / RTS 20111127
# Part of code from Luc Dekens http://communities.vmware.com/message/1680735

# Here i extended Luc´s function for moving only config
function Move-VMs{
    param($vm)
	Write-Host $vm
    $HDDs = Get-HardDisk -VM $vm    
	# a foreach loop to move vmdk
	$HDDs | %{
		# Get the datastore name of the old
		$oldDS = $_.Filename.Split(']')[0].TrimStart('[')
		# as @pfuhli said the new lun has a preceding letter that differs from the old.
		$newDS = "N" + $oldDS 
		# Here i check which is the first hdd to later move the config there
		if ($_.Name -eq "Hard disk 1"){
			$dsNameHDD1 = $newDS
		}
		$newDS = Get-Datastore $newDS
		Set-HardDisk -HardDisk $_ -Datastore $newDS -Confirm:$false
	}
	
	# This part is for moving the config file
	$HDDs = Get-HardDisk -VM $vm
	$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec 
	$spec.datastore = (Get-Datastore -Name $dsNameHDD1).Extensiondata.MoRef
    $HDDs | %{
        $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
        $disk.diskId = $_.Extensiondata.Key
        $disk.datastore = $_.Extensiondata.Backing.Datastore
        $spec.disk += $disk
    }
    $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")
}

Get-VM | %{ 
	Move-VMs $_ 
}

 

Before running it on all VM´s i would test it on a few and then when feeling comfortable, you can move all 😀