Clone-CustomAttributes using PowerCLI

There is nothing to explain i guess in this function. Just copies the definitions of custom attributes between 2 virtual center servers. It expects that you are connected to both virtual centers.

Function Clone-CustomAttributes 
{
<#
    .SYNOPSIS
        Copies custrom attributes used for annotations , just the definitions.
  
    .DESCRIPTION
        Copies custrom attributes used for annotations , just the definitions.
  
    .PARAMETER  sourceVC
        Specify the Virtual Center from which it will download the custom attributes.

    .PARAMETER  destinationVC
        Specify the Virtual Center to which it will apply the custom attribues.
          
    .PARAMETER  TargeType
        Specify for which kind of attributes this list will be generated: VirtualMachine,ResourcePool, 
        Folder,VMHost,Cluster,Datacenter. Global is not included in this version.

    .EXAMPLE
        PS C:\> Clone-CustomAttributes -sourceVC 'VC01.biz' -destinationVC 'vc02.biz' -TargetType 'VirtualMachine'
        Will create the custom attribute definitions for type VirtualMachine which belong to VC01 on VC02.

    .NOTES
        NAME:  Export-CustomAttributes
          
        AUTHOR: Grzegorz Kulikowski
          
        NOT WORKING ? #powercli @ irc.freenode.net 
          
    .LINK
  
https://psvmware.wordpress.com
  
#>
param(
[Parameter(Mandatory=$true)]$sourceVC, 
[Parameter(Mandatory=$true)]$destinationVC, 
[Parameter(Mandatory=$true)][VMware.VimAutomation.ViCore.Types.V1.AnnotationManagement.CustomAttributeTargetType]$targetType

) 
    $SourceCustomAttr = @{}
    #I have special filter not to much some names, as i do not wan't them on my new VC Instance.
    Get-CustomAttribute -Server $sourceVC -TargetType $targetType  | ? {$_.Name -notmatch "PnC|vrm|FA.|Xd"} | % { $SourceCustomAttr+=@{$_.Key=$_.Name}}
    Foreach ($CustomAttribute in $SourceCustomAttr.GetEnumerator()) 
    {
        New-CustomAttribute -Name $CustomAttribute.Value -TargetType $targetType -Server $destinationVC
    }
}
Advertisements

Export-CustomAttributes using PowerCLI

Ok , exporting values of custom attributes , in other words our custom annotations for vms.
When running with specific -Attribute parameter :

When running without the -Attribute parameter it will grab all annotations for the specific target type (VirtualMachine,ResourcePool, Folder,VMHost,Cluster,Datacenter).

I have not implemented the ‘global’ target type here. Might be the case that i will do it later on.
The idea behind is to save the report to a file , and then with the import function , apply to vms that were imported to the new VC.

Function Export-CustomAttributes
{
<#
    .SYNOPSIS
        Returns VM report with custom attributes for vms that have currently custom attributes applied.
  
    .DESCRIPTION
        Returns VM report with custom attributes for vms that have currently custom attributes applied.
        Can be ran with the -Attribute parameter to specify which exactly attributes should be recorded.
        Cmdlet expects that we are already connected to a specified virtual center system. The sourceVC
        parameter is needed to distinguish between VC if you are connected to more than 1 VC. It also 
        used as the identificator of VC connection if you are connected to a single VC instance.
  
    .PARAMETER  sourceVC
        Specify the Virtual Center from which it will download the report.
          
    .PARAMETER  TargeType
        Specify for which kind of attributes this list will be generated: VirtualMachine,ResourcePool, 
        Folder,VMHost,Cluster,Datacenter. Global is not included in this version.

    .PARAMETER  Attribute
        Specify for which attributes this list will be generated, you can check which one you have by 
        running get-customattributes cmdlet. Attributes inside the specific TargetType only.
 
    .EXAMPLE
        PS C:\> $CA = Export-CustomAttributes -sourceVC 'VC004.domain.biz' -targetType 'virtualmachine' -Attribute 'ApplicationOwner','Function'
        Will get 2 custom attribute for all virtualmachine that have currently customattributes

    .EXAMPLE
        PS C:\> $CA = Export-CustomAttributes -sourceVC 'VC004.domain.biz' -targetType 'virtualmachine'
        Will get all custom attributes from virtualmachine type for all virtualmachine that have currently customattributes
         

    .NOTES
        NAME:  Export-CustomAttributes
          
        AUTHOR: Grzegorz Kulikowski
          
        NOT WORKING ? #powercli @ irc.freenode.net 
          
    .LINK
  
https://psvmware.wordpress.com
  
#>
param(
[Parameter(Mandatory=$true)][string]$sourceVC, 
[Parameter(Mandatory=$true)][VMware.VimAutomation.ViCore.Types.V1.AnnotationManagement.CustomAttributeTargetType]$targetType, 
[string[]]$Attribute
)
#▅▇█▓▒░Don't forget to implement the global option as per :http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.wssdk.apiref.doc/vim.CustomFieldsManager.FieldDef.html
#▅▇█▓▒░Right now the $targetType can't be null, so we can't take 'globals' , globals are the ones which are empty.
    
    $SourceCustomAttr = @{}
    if ($Attribute) 
    {
        Get-CustomAttribute -Server $sourceVC -TargetType $targetType -Name $Attribute | % { $SourceCustomAttr+=@{$_.Key=$_.Name}}
    } else 
        {
            #This is custom to the environment, depending on which plugins you were installing to your VC, you might have different special attributes, which might not be needed on the other side.
            Get-CustomAttribute -Server $sourceVC -TargetType $targetType  | ? {$_.Name -notmatch "PnC|vrm|FA.|Xd"} | % { $SourceCustomAttr+=@{$_.Key=$_.Name}}
        }
    #get only those that have custom attributes     
    $SourceVms = Get-View -ViewType virtualmachine -Property 'CustomValue','Name' -Server $sourceVC | ?{$_.customvalue}
    $ReportSourceVms = $SourceVms | Select Moref,Name,CustomValue
    
    Foreach ($VM in $ReportSourceVms) 
    {
        foreach ($CustomAttribute in $SourceCustomAttr.GetEnumerator()) 
        {
            Add-Member -InputObject $VM -MemberType NoteProperty -Name $CustomAttribute.Value -Value ($VM.CustomValue|?{$_.Key -eq $CustomAttribute.Name}).value
        }
    }
    return $ReportSourceVms | Select-Object * -ExcludeProperty CustomValue
} 

Get-gEvents for getting vsphere events with some additional filtering

Some time ago i wrote a dirty function that utilizes eventfilterspec to filter out events. I knew it had one flaw, because as far as i remember i was using there QueryEvents method. Nothing bad with that, but as far as i understand it will only return up to 1000 records. So i have finally modified it so it uses EventCollector. It has support for searching by eventchainID, eventTypeId, username, date. I have tried to document function as much as possible. For me it works ok. There is some tiny support for checking eventTypeIds inside the function. If something is not clear make sure you will read the help
get-help get-gEvents -full
One confusing bit might be that while passing the entityname , you have to pass the viewtype as well. Well i did it because i use it this way 😉 So i use Get-View -ViewType [type] -Filter @{‘name’=XXX’}
So it’s up to you what exactly you are looking for, while specifying the entity, In filter name will be put, but ViewType specifies the type of object, whether it will be a datacenter, vm , cluster, datastore etc..
I tried to implement the switch for enabling/disabling full formatted message, but for some reason it was not working, no idea why.

Quick examples:

How to check how many vmotions DRS has performed inside a particular cluster ?

(Get-gEvents -StartDate (get-date).AddDays(-1) -types 'VmBeingHotMigratedEvent' -EntityName 'Cluster_name' -ViewType ClusterComputeResource).Count

How to check how many vmotions DRS has performed inside a particular datacenter ?

(Get-gEvents -StartDate (get-date).AddDays(-1) -types 'VmBeingHotMigratedEvent' -EntityName 'Datacenter_name' -ViewType Datacenter).count

Endless possibilities basically.. i will throw 1 more
How many times user X has powered off a VM in last 7 days

(Get-gEvents -StartDate (get-date).AddDays(-7) -EventTypeIds 'VmPoweredOffEvent' -EventUsername 'DOMAIN\UserX' -systemUser:$false ).count

How many were there vmotions in some cluster during last 7 days

Get-gEvents -StartDate (get-date).AddDays(-7) -EventTypeIds 'VmFailedMigrateEvent' -EntityName 'SomeCluster' -ViewType ClusterComputeResource}

What if you want to check for other dates ? Use: -StartDate with (get-date).AddDays(-7) for example, to go 7 days back. Same goes for end date, -EndDate (get-date…..

When you will be giving parameter for the Entity, you can still use the -Recursion parameter with it to control whether you want to inspect only THAT entity, or its children, or both.

If you will skip -startdate or -enddate make sure you know that function is setting those variable up anyway with default values of: Enddate -> NOW , -startdate 7 days ago.

Make sure you know that by default if you will skip those parameters : systemuser and recursion will be set to true and all . So if you wonder how come you received system events if you were looking for user’s events, mark the -systemuser:$false , if you want to look only for event on entity and do not want to step inside its children use -recursion ‘self’ , because by default i set it to ‘all’.

You do not need to provide entity for this function to start, if not given it searches through everything.

Enjoy

function Get-gEvents
{
  <# .SYNOPSIS Get-gEvents is utilizing EventCollector to get information about events. .DESCRIPTION Get-gEvents utilizies most of what EventCollector has to offer. If Start or End date is not specified, the default values of: End - Now, Start - last 7 days will be applied. If you are using EventUserName parameter, you can then choose SystemUser parameter. By default it is selected as True, so if you do not want to see system events please set it to -SystemUser:$false , so you will get only user's records. This function also allows to get current list of types for events, if you do not remember a particular event, first try this function with -ListMainEVTypes From there you can use -ListSecEVTypes with -SubEVType and give it value of name of typse from previous command. .EXAMPLE Count DRS vmotions in Virtual Center for last day. (Get-gEvents -StartDate (get-date).AddDays(-1) -EventTypeIds 'VmBeingHotMigratedEvent').count .EXAMPLE Get-gEvents -ListSecEVTypes -SubEVType 'VmEvent' .PARAMETER ListMainEVTypes If used , you will received main event types categories. .PARAMETER ListSecEVTypes If used, you have to use SuvEVType to select the right subcategory to expand. .PARAMETER SubEVType From output of -ListMainEVTypes you can paste its name to -SubEVType , in response you will get more detailed event types. for example -SubEVType 'VmEvent' .PARAMETER eventChainId If you are interested only in particular event chain you can specify it's id here. .PARAMETER EventUsername You can search only user's events by giving in this parameter the login of user for example: 'userX', 'DOMAIN\UserX' .PARAMETER EntityName Name of the entity for which or underwhich you will be looking for events. It works together with ViewType. .PARAMETER systemUser In use with EventUsername, By default systemUser is $True, so that you will see the user's and the system events. If you will give -systemUser:$false then, only user's events will be gathered. .PARAMETER EventTypeIds This parameters can handle multiple ids of eventtypes separated by comas, for example : VmBeingHotMigratedEvent for checking drs migrations or VmPoweredOffEvent for vms getting powered off. If you do not know the specific type id, you can always run this function with ListMainEVTypes and ListSecEVTypes paramegters to get hints. .PARAMETER category Possible categories are: info, warning, error, user. .PARAMETER StartDate Start date for the search query. For example (get-date) for now, or (get-date).AddDays(-1) for yesterday. .PARAMETER EndDate End date for the search query. For example (get-date) for now, or (get-date).AddDays(-1) for yesterday. .PARAMETER Recursion You can choose from Self,Children,All options. Self is only checking events on Entity itself, Childred only on Children entities, and all is Self+Children. .PARAMETER ViewType This is the ViewType that you would normally use within Get-View to find that particular entity. For example HostSystem for host, or VirtualMachine for VM, or ClusterComputeResource for Cluster. .LINK https://psvmware.wordpress.com .NOTES Author : Grzegorz Kulikowski #>
	[cmdletbinding(DefaultParametersetName = "Main Usage")]
	param (
		[parameter(Mandatory = $true, ParameterSetName = "Main Events Types Listing")][switch]$ListMainEVTypes,
		[parameter(Mandatory = $true, ParameterSetName = "Detailed SubEvents Types Listing")][switch]$ListSecEVTypes,
		[parameter(Mandatory = $true, ParameterSetName = "Detailed SubEvents Types Listing")]$SubEVType,
		[parameter(Mandatory = $true, ParameterSetName = "ChainID Events Listing")][string]$eventChainId,
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][string[]]$EventUsername,
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][bool]$systemUser = $true,
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][string]$EntityName,
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][String[]]$EventTypeIds,
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][VMware.Vim.EventCategory]$category,
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][datetime]$StartDate = (Get-Date).AddDays(-7),
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][datetime]$EndDate = (Get-date),
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][vmware.vim.EventFilterSpecRecursionOption]$Recursion = 'all',
		[parameter(Mandatory = $false, ParameterSetName = "Main Usage")][ValidateSet('ClusterComputeResource', 'ComputeResource', 'Datacenter', 'Datastore', 'DistributedVirtualPortgroup', 'DistributedVirtualSwitch', 'Folder', 'HostSystem', 'Network', 'OpaqueNetwork', 'ResourcePool', 'StoragePod', 'VirtualApp', 'VirtualMachine', 'VmwareDistributedVirtualSwitch')][string]$ViewType
	)
	
	switch ($PsCmdlet.ParameterSetName)
	{
		"Main Events Types Listing"  {
			[VMware.Vim.VmEvent].Assembly.GetTypes() | ? { $_.BaseType -eq [VMware.Vim.Event] }
			break
			
		}
		"Detailed SubEvents Types Listing"  {
			
			[VMware.Vim.VmEvent].Assembly.GetTypes() | ? { $_.BaseType -like "VMware.Vim.$SubEVType" }
			break
		}
		"Main Usage" {
			$si = get-view -id ServiceInstance
			$em = get-view -id $si.Content.EventManager
			
			$EventFilterSpec = New-Object VMware.Vim.EventFilterSpec
			$EventFilterSpec.eventTypeId = $EventTypeIds
			if ($StartDate -or $EndDate)
			{
				Write-debug "Date was given"
				$EventFilterSpec.Time = New-Object Vmware.Vim.EventFilterSpecByTime
				$EventFilterSpec.Time.beginTime = $StartDate
				$EventFilterSpec.Time.endTime = $EndDate
			}
			if ($category)
			{
				Write-debug "Category was given"
				$EventFilterSpec.Category = $category
			}
			if ($EventUsername)
			{
				Write-debug "User was given"
				$EventFilterSpec.userName = New-Object Vmware.Vim.EventFilterSpecByUsername
				$EventFilterSpec.userName.systemUser = $systemUser
				$EventFilterSpec.userName.userList = $EventUsername
			}
			if ($EventChainId)
			{
				Write-debug "EventChainId was given"
				$EventFilterSpec.EventChainId = $EventChainId
			}
			if ($EntityName)
			{
				Write-debug "Entity was given"
				$entity = get-view -viewtype $ViewType -Filter @{ 'name' = $EntityName } -Property name
				$EventFilterSpec.Entity = New-Object VMware.Vim.EventFilterSpecByEntity
				$EventFilterSpec.Entity.Entity = $entity.moref
				$EventFilterSpec.Entity.Recursion = $Recursion
			}
			$EventCollector = get-view -id $EM.CreateCollectorForEvents($Eventfilterspec)
			$EventCollector.RewindCollector()
			write-debug "Collector rewinded"
			$events = $null
			
			
			while ($EventInWindow = $EventCollector.ReadNextEvents(100))
			{
				$Events += $EventInWindow
				write-debug "Reading next window"
			}
			$EventCollector.DestroyCollector()
			$Events
			break}
	}
	
	
}

vLanIdentificator – for checking subnets for Virtual Machines and their vlan info.

I have created this tiny program that will help me sometimes look for other vms that are supposed to sit inside some particular vlan/subnet. The idea is really simple. You are given an ip and somebody is asking you which vlan is that , for example. If you don’t have a hobby of memorizing vlans in your networks might try to use this program. If given a particular IP, and netmask, it will scan all ips within it and check if you have Virtual Machines in Virtual Center that are utilizing ips from that range. In addition it will tell you where the VM is being hosted and which portgroup on esxi hostsystem it is utilizing and of course its vlan id. I hope some of you may find it useful. Executable is prepared for powershell version 3. In general i guess it’s compatible only with >PowerShell 3 , since how i wrote it. I have not tested it yet with Distributed Switches. I have not tested it on other version than vsphere 5.0.If you test it on different version , let me know in the comment. I will make sure it runs ok with vDS as well soon. VMware tools need to be installed in VM in order to report the IP back. This tiny program basically just runs a loop for ips utilizing SearchIndex and its FindAllByIp function. There isn’t much magic happening here 😉 In order to write it i used Get-IPrange by Barry Chum – https://goo.gl/TBYujC IP regex – http://goo.gl/Ow7PFf On the computer on which you want to run it , you will need to have PowerCLI installed. When you are asked for credentials, read-only permission will be enough to retrieve information. Screenshot of how it looks is below. vlanidentificator Executable can be found HERE PSF (Powershell Studio) source code can be found HERE No this is not finished 😉 I am still learning windows forms, so that’s why it looks like it looks. Most important for now , is that it does its job. –Update 21/07/2015 Added support for VMware Distributed Switches Fixed minor bugs

Listing vSphere alarms actions other than SendEmail, ExecuteScript, SendSNMP

It’s gonna be quick one today.

If you are familiar with dell openmanage integration plugin for vSphere Virtual Center, you know that it can create custom alarms. Those alarms can be triggered, and an action will be performed. What action you might wonder ? Put host into maintenance mode. If you are wondering which alarms will do this, here it is how to quickly check this.

Before we start you should know that Get-AlarmAction supports only ‘SendEmail’, ‘ExecuteScript’, ‘SendSNMP’ , since those dell alarms have something else then that, we have to change our approach to get them.
That is our alarm defined by dell openmanage integration. We want to check the actions from it.
o4

Getting the alarm definitions:

$DellAlarmDefinitions = Get-AlarmDefinition  -Name 'Dell*'
$DellAlarmDefinitions | ? {$_.Extensiondata.Info.Action.Action.Action} |Select Name, Description

o1

What is being checked is the Action object in the alarm definition. We inspect the view of the alarm by checking .Extensiondata:

o6
We can also easily make a table : Alarm name | Action to be taken

o3

Below is the source of what’s on the screenshot:

($DellAlarmDefinitions | ? {$_.Extensiondata.Info.Action.Action.Action}) | Select Name, @{n='Action';e={$_.Extensiondata.Info.Action.Action.Action.Name}}

This might now work within Powershell v2, so make sure you are running this in v3, or modify the lines.