PowerCLI

 View Only
  • 1.  Modify VM with custom attributes defined in a CSV

    Posted Oct 10, 2012 08:00 PM

    Hi All,

    I am trying to do something that I think should be simple (but this is the first time I'm using powercli and am not a good code writer), but I'm finding it challenging to say the least.

    I created 2 custom attributes (Business System Owner and SSG System Owner) in vCenter for my virtual machines.  I have a csv list of the vm names and their associated "owners".  I'd like to use powercli to read that csv file and connect to the VC server and input the "owners" in the appropiate field.

    I've borrowed com code from various places across the internet and these forums but I cannot seem to make it all work.  I have been successful in at least reading in the information from the csv file and getting it displayed on my laptop screen.  What I can't seem to do is get the 3 columns in the csv file to be recognized as variables (unless there are some default variables I don't know about) that I can put into the Set-Annotation lines. 

    The code I have is :

    # Input array, includes all VM names from DCI that are registered.
    $data = Import-Csv "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\vmowners1.csv" -Header('Hostname','Business Owner', 'SSG Owner')
    ####$data |Get-Member
    Write-Output $data
    # Loop through all VMs within vCenter
    ForEach ($row in $data)
    {
         # Create variables for the current VM and its "Contact" and "Description" which are custom attribute fields.  Also create a string $note to use with Set-VM -Description
        $hostname = Get-VM -Name $vmname;
    ###     $contact = $vm | Get-Annotation -CustomAttribute User;
    ###     $description = $vm | Get-Annotation -CustomAttribute Description;
    ###     $note = $contact.name+":`t"+$contact.value+"`n`n"+$description.name+":`t"+$description.value;
    Set-Annotation -Entity $hostname -CustomAttribute "Business System Owner" -value $SSG_owner
    Set-Annotation -Entity $hostname -CustomAttribute "SSG System Owner" -value $system_owner
    ### Set-VM -VM $vm -Description $note -Confirm:$false;
    }

    The output I get on my screen is :

    PowerCLI C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts> .\setvmownership.ps1

    Hostname                                              Business Owner                                       SSG Owner

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

    ABPPROXY-00-AH

    ACE-01-AH                                             Morade Laallmmi                                      Morade Laallmmi

    Get-VM : Cannot validate argument on parameter 'Name'. The argument is null or empty. Supply an argument that is not null or empty and then try the command aga

    in.

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\setvmownership.ps1:13 char:29

    +     $hostname = Get-VM -Name <<<<  $vmname;

        + CategoryInfo          : InvalidData: (:) [Get-VM], ParameterBindingValidationException

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

    Set-Annotation : Cannot validate argument on parameter 'Entity'. The argument is null. Supply a non-null argument and try the command again.

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\setvmownership.ps1:17 char:23

    + Set-Annotation -Entity <<<<  $hostname -CustomAttribute "Business System Owner" -value $SSG_owner

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

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

    Set-Annotation : Cannot validate argument on parameter 'Entity'. The argument is null. Supply a non-null argument and try the command again.

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\setvmownership.ps1:18 char:23

    + Set-Annotation -Entity <<<<  $hostname -CustomAttribute "SSG System Owner" -value $system_owner

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

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

    Get-VM : Cannot validate argument on parameter 'Name'. The argument is null or empty. Supply an argument that is not null or empty and then try the command aga

    in.

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\setvmownership.ps1:13 char:29

    +     $hostname = Get-VM -Name <<<<  $vmname;

        + CategoryInfo          : InvalidData: (:) [Get-VM], ParameterBindingValidationException

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

    Set-Annotation : Cannot validate argument on parameter 'Entity'. The argument is null. Supply a non-null argument and try the command again.

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\setvmownership.ps1:17 char:23

    + Set-Annotation -Entity <<<<  $hostname -CustomAttribute "Business System Owner" -value $SSG_owner

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

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

    Set-Annotation : Cannot validate argument on parameter 'Entity'. The argument is null. Supply a non-null argument and try the command again.

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\setvmownership.ps1:18 char:23

    + Set-Annotation -Entity <<<<  $hostname -CustomAttribute "SSG System Owner" -value $system_owner

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

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

    The CSV file looks like this (but goes on for about 500 vm's:

    I did go with the import-csv option because something i read in my troubleshooting efforts said that the blank columns would cause and error that I was getting and that import-csv would properly intrepret the empty columns.

    hostname,business_owner,system_owner,,,,,,,,,,,,,,,,,,,,,,,,

    ABPPROXY-00-AH,,,,,,,,,,,,,,,,,,,,,,,,,,

    ACE-01-AH,Morade Laallmmi,Morade Laallmmi,,,,,,,,,,,,,,,,,,,,,,,

    acrodev-00-ah,tflessa,Bruce Hastings,,,,,,,,,,,,,,,,,,,,,,,,

    ACT1DDB00AH,Bill Mancini,Mike Bruni,,,,,,,,,,,,,,,,,,,,,,,,

    ACT1TDB00AH,Bill Mancini,Mike Bruni,,,,,,,,,,,,,,,,,,,,,,,,

    What do I need to do to be able to get this script to work? I am sure it's related to the "The argument is null." messages that are seen in the output.

    Thanks

    Dan



  • 2.  RE: Modify VM with custom attributes defined in a CSV
    Best Answer

    Posted Oct 11, 2012 02:54 AM

    Hello, dscottimw-

    You were on the right track.  There were a couple of things to change to get it working as desired:

    1. either remove the "-Header" portion of the Import-Csv line, or remove the actual header row from the CSV itself -- these are conflicting items (the "-Header" param names the columns of the CSV and assumes that the CSV has no header row already)
    2. you needed to access the properties of the $row variable in the ForEach loop -- not just call the names of the column headers from the CSV (that was why you were getting the errors about "null" things -- you were using variables that had no values)

    Try it like:

    # Input array, includes all VM names from DCI that are registered.
    $arrVMsInfo = Import-Csv "C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\scripts\vmowners1.csv"
    #Write-Output $data

    ## loop through all VMs listed in the CSV, setting custom attrib values for each
    ForEach ($row in $arrVMsInfo) {
       
    ## get the VM for this row
        $vmThisOne = Get-VM -Name $row.hostname
       
    Set-Annotation -Entity $vmThisOne -CustomAttribute "Business System Owner" -Value $row.business_owner
       
    Set-Annotation -Entity $vmThisOne -CustomAttribute "SSG System Owner" -Value $row.system_owner
    }
    ## end foreach

    And, to give it a shot without actually doing the set on the annotations, to make sure things are going to go as you want, you could append a -WhatIf to each Set-Annotation line in the ForEach loop.

    Does that work better for you?



  • 3.  RE: Modify VM with custom attributes defined in a CSV

    Posted Oct 11, 2012 02:04 PM

    Matt,

    thanks that worked exactly as I had hoped. I tested it on a small subset of my vm's first.  What it has pointed out is that our database that contains the inventory information is not accurate anymore. Sigh!

    Thanks a ton for getting me going on this.

    One question though. Is there a way to connect (using connect-viserver or some other method) to multiple vitrual centers at the same   time or is it better to do them one at a time?

    Thanks so much for your help and prompt reply.

    Dan



  • 4.  RE: Modify VM with custom attributes defined in a CSV

    Posted Oct 12, 2012 12:32 AM

    Hello, Dan-

    Good, glad to hear it.  D'oh!  Well, of course it couldn't be easy for you.

    Yes, you are welcome.

    And, yes -- you can connect to as many vCenters and/or vSphere hosts as you want (probably up to some limit, but I have not seen the limit, yet).  You can just use Connect-VIServer again to connect to another vCenter server (or pass an array of vCneter names to which to connect).  There is a PowerCLI config item, "DefaultVIServerMode", that dictates how Connect-VIServer behaves.

    We wrote about this at vNugglets.com a while ago in the post "Working with multiple default servers" (written in the PowerCLI v4 days, but still pertinent).  The first time you connect to more than one VIServer, you will be prompted about the DefaultVIServerMode.

    So, you could connect to all of the vCenters in which you have machines to update, and then just let the script chug.  One thing to note:  for performance, it will likely be better to connect to one vCenter at a time (or use the -Server param as discussed later), act on the given subset of VMs in that vCenter, disconnect, and repeat for each vCenter.  This is due to the way that the PowerCLI cmdlets behave when connected to multiple VIServers at once:  they act against _all_ of the VIServers by default.

    If you do want to connect to all vCenters at the same time and then run the script, you might consider adding the -Server param to the Get-VM and Set-Annotation calls -- that will have the effect of only contacting server that you specify in the command line for that given operation.