VMware Cloud Community
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

annotation scripting

I currently get a spreadsheet of system names and the values, many of which are not annotations.
I pull out the system names, and the value I need to add/update, massage that data as needed (mainly fixing the system name) and then run this script.

<code>

Import-CSV .\data.csv |for-each-object
{

set-annotation -Entity $_,vmname -customattribute "attrib-name" -value $_.value

}

</code>

I'd like to simplify what I do, and set all of the annotations from one spreadsheet, so I am just massaging it once, instead of once per annotation.

TIA!!

~Jahn

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Ok, got it.

In that case try this slightly changed script

foreach($row in (Import-CSV .\data.csv)){

   $vm = Get-VM -Name $row.'System Name'

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'System Name'} | select -ExpandProperty Name)){

      Try{

        $ca = Get-CustomAttribute -TargetType VirtualMachine -Name $prop -ErrorAction Stop

      }

      Catch{

        $ca = New-CustomAttribute -TargetType VirtualMachine -Name $prop -Confirm:$false

      }

      Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity $vm -Confirm:$false

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
18 Replies
LucD
Leadership
Leadership
Jump to solution

Unfortunately the Set-Annotation cmdlet only accepts 1 custom attribute per call.

So I don't think what you want to do is possible.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

Thanks for the response.
SInce set-annotation won't take multiple attributes, how about cycling through the systems names from column 1, doing each of the following columns containing 8 different annotations?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That's possible, can you show a sample row of the file?
Do you have 1 or more custom attributes on a row in the file?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

The current csv for the above script is very simple, for this one, "owner".

Header 1Header 2
VMnameValue
servername*First@Last.domain.com

The spreadsheet that I get and massage is like this

Header 1Header 2Header 3Header 4Header 5
System NameownercreatedtierManaged-by
servername.domain.com
First@Last.domain.com
01/02/20183team-1
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Starting from that 2nd CSV you could do something like this

foreach($row in (Import-CSV .\second.csv)){

   $vm = Get-VM -Name $row.'System Name'

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'System Name'} | select -ExpandProperty Name)){

     Get-Annotation -Entity $vm -Name $prop |

     Set-Annotation -Value $row."$prop" -Confirm:$false

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

TY! I'm gonna try this out pretty quick

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

Well bummer, this didn't work. Here is the first and second error, there are many more, they were all the rest of the other annotations.
<CODE>

Set-Annotation : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input

and its properties do not match any of the parameters that take pipeline input.

At C:\Users\user1\Desktop\scripts\powercli\connect\annotations\one-script\set-anno-one-scr.ps1:10 char:6

+      Set-Annotation -Value $row."$prop" -Confirm:$false

+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (CreatedBy:JS:PSObject) [Set-Annotation], ParameterBindingException

    + FullyQualifiedErrorId : InputObjectNotBound,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetAnnotation

Set-Annotation : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input

and its properties do not match any of the parameters that take pipeline input.

At C:\Users\user1\Desktop\scripts\powercli\connect\annotations\one-script\set-anno-one-scr.ps1:10 char:6

+      Set-Annotation -Value $row."$prop" -Confirm:$false

+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (CreatedOn:11/30/2011 22:00:PSObject) [Set-Annotation], ParameterBindingException

    + FullyQualifiedErrorId : InputObjectNotBound,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetAnnotation

</CODE>

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Do these Custom Fields already exist or are they new, and to be created?

Which PowerCLI version are you using?

And can you include the script as you are using it?

And a sample line from the CSV you are using?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

Yes, I update them with the script at the top of this chain, albeit one at a time.

VMWARE PowerCLi 10.0.0 build 7895300

foreach($row in (Import-CSV .\data.csv)){

   $vm = Get-VM -Name $row.'System Name'

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'System Name'} | select -ExpandProperty Name)){

     Get-Annotation -Entity $vm -Name $prop |

     Set-Annotation -Value $row."$prop" -Confirm:$false

   }

}

This is cleaned up, removing "personal" data. It is from notepad, after openeing the csv in it.

System Name,Program,Project Code,(StorageCode),(ServerCode),Environment,Managed By,Location,Owner,CreatedBy,CreatedOn

server1*,pr1,123456,code1,NULL,Tier 1,E3,dc1,"name,name","name,name",1/2/2018

server2*,pr2,234567,code2,code3,Tier 1,E4,dc1,"name,name","name,name",1/3/2017

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You have 'System Name' values with an asterisk in there, those can return more than 1 VM.

Is that the intention?

The script I gave is not foreseen for that I'm afraid.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

Yes, the names of the systems in ESX unfortunately do not follow a convention, sometimes it is FQDN, sometimes not, can be in be different domain also. I have found that using the wildcard after the name gets it to find the systems. This has not been a problem for me for any other scripts I run.There are not duplicates of the names.
I tried setting the name so it is exactly the same as the VM, without the asterisk, and I got the same error.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, got it.

In that case try this slightly changed script

foreach($row in (Import-CSV .\data.csv)){

   $vm = Get-VM -Name $row.'System Name'

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'System Name'} | select -ExpandProperty Name)){

      Try{

        $ca = Get-CustomAttribute -TargetType VirtualMachine -Name $prop -ErrorAction Stop

      }

      Catch{

        $ca = New-CustomAttribute -TargetType VirtualMachine -Name $prop -Confirm:$false

      }

      Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity $vm -Confirm:$false

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

Was this supposed to try and create a custom attribute? I would not want that..... Here is first three errors, the errors repeats for the other attributes.

The script did not update any fields.

<code>

New-CustomAttribute : 5/10/2018 7:47:34 AM    New-CustomAttribute        The name 'CreatedBy' already exists.

At c:\script\run.ps1:15 char:15

+ ...       $ca = New-CustomAttribute -TargetType VirtualMachine -Name $pro ...

+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [New-CustomAttribute], DuplicateName

    + FullyQualifiedErrorId : Client20_InventoryServiceImpl_NewAnnotation,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewCustomAttribute

New-CustomAttribute : 5/10/2018 7:47:34 AM    New-CustomAttribute        The name 'CreatedBy' already exists.

At C:\scripts\run.ps1:15 char:15

+ ...       $ca = New-CustomAttribute -TargetType VirtualMachine -Name $pro ...

+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [New-CustomAttribute], DuplicateName

    + FullyQualifiedErrorId : Client20_InventoryServiceImpl_NewAnnotation,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewCustomAttribute

Set-Annotation : Cannot validate argument on parameter 'CustomAttribute'. The argument is null. Provide a valid value for the argument, and then try

running the command again.

At C:\scripts\run.ps1:19 char:39

+       Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity ...

+                                       ~~~

    + CategoryInfo          : InvalidData: (:) [Set-Annotation], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetAnnotation

</code>

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is strange, the Try-Catch first tries to get the Custom Attribute, only when it does not exist, will the script create it.

So you probably already have a Custom Attribute by that name, but probably not assigned to that TargetType.

Do a Get-CustomAttribute -Name 'CreatedBy', and check what the TargetType says.

If blank, leave out the TargetType parameter from the Custom Attribute cmdlets.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

Key     Name                TargeType

---        ----                     ---------------

8         CreatedBy      

202     CreatedBy

Is it normal to see 2, did I create one?

I removed the targettype from the script.

I changed the catch to tell me the custom attribute does not exist, though I know the ones I have in the csv are valid.

I also changed the column 1 header to Server, so that spaces can't be an issue.
<code>

foreach($row in (Import-CSV .\data.csv)){

   $vm = Get-VM -Name $row.'Server'

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'Server'} | select -ExpandProperty Name)){

      Try{

        $ca = Get-CustomAttribute -Name $prop -ErrorAction Stop

      }

      Catch{

        write-host The custom attribute does not exist.

      }

      Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity $vm -Confirm:$false

   }

}

</code>

<error>

Set-Annotation : Cannot convert 'System.Object[]' to the type 'VMware.VimAutomation.ViCore.Types.V1.AnnotationManagement.CustomAttribute' required by

parameter 'CustomAttribute'. Specified method is not supported.

At C:\scripts\run.ps1:18 char:39

+       Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity ...

+                                       ~~~

    + CategoryInfo          : InvalidArgument: (:) [Set-Annotation], ParameterBindingException

    + FullyQualifiedErrorId : CannotConvertArgument,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetAnnotation

</error>

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There are seemingly 2, but they are not same in my opinion.
So $ca is an array with 2 entries, and that is why the Set-Annotation fails.

Remove the custom attribute with the Remove-CustomAttribute, but use the Id parameter instead of the Name


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Squigglymonkey
Enthusiast
Enthusiast
Jump to solution

When I use powercli, I connect to 2 vcenter hosts, one internal, and one dmz. That is why there was 2 for the same name. When I restarted my session, and I only connected to one host, the script worked!
Below is the final script  that worked for me.
Would it be easy to get the output to be like this:
server     created    owner              backup

--------     ----------     -------               ----------

server1   1-2018     name,name     virtual

server2   1-2018     name,name     tape


<code>

foreach($row in (Import-CSV .\data.csv)){

   $vm = Get-VM -Name $row.'Server'

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'Server'} | select -ExpandProperty Name)){

      Try{

        $ca = Get-CustomAttribute -Name $prop -ErrorAction Stop

      }

      Catch{

        write-host The custom attribute does not exist.

      }

      Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity $vm -Confirm:$false

   }

}

</code>

Thank you so much!!

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try like this

$report = foreach($row in (Import-CSV .\data.csv)){

   $vm = Get-VM -Name $row.'System Name'

   $obj = [ordered]@{

     Server = $vm.Name

   }

   foreach($prop in ($row | gm -MemberType NoteProperty | where{$_.Name -ne 'System Name'} | select -ExpandProperty Name)){

      Try{

        $ca = Get-CustomAttribute -TargetType VirtualMachine -Name $prop -ErrorAction Stop

      }

      Catch{

        write-host "The custom attribute $prop does not exist."

      }

      Set-Annotation -CustomAttribute $ca -Value $row."$prop" -Entity $vm -Confirm:$false

      $obj.Add($prop,$row."$prop")

   }

   New-Object PSObject -Property $obj

}

$report | Export-Csv .\report.csv -NoTypeInformation -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos