7 Replies Latest reply on Jul 7, 2011 9:34 PM by LucasAlbers

    Script to find all  VM's with out dates/not installed tools.

    peter79 Enthusiast

      Hey,

       

      I need some help guys.  I need a script that will find all VM's in vCenter that either have not tools installed or tools that or out of date.  I also need the script to output the following data to a CSV file.  Name of VM and the status of the tools (either not installed or out of date).

       

      Thanks guys.

        • 1. Re: Script to find all  VM's with out dates/not installed tools.
          RvdNieuwendijk Virtuoso
          User ModeratorsvExpert

          Try the next PowerCLI script:

           

          Get-VM | Get-View | `
          Select-Object @{N="Name";E={$_.Name}},@{Name="ToolsStatus";E={$_.Guest.ToolsStatus}} | `
          Where-Object {$_.ToolsStatus -ne "toolsOK"} | `
          Export-CSV -Path VmToolsStatus.csv -NoTypeInformation -UseCulture
          
          


          Regards, Robert

          1 person found this helpful
          • 2. Re: Script to find all  VM's with out dates/not installed tools.
            mattboren Master
            vExpert

            Hello-

             

            Pretty good looking script posted by RvdNieuwendijk, for sure.  Gets the info requested, indeed.

             

            I wanted to add something about the speed of the script, though, and provide a quick/easy way to get a substantial speed increase.

             

            Instead of using Get-VM piped to Get-View to get .Net View objects of all of the VMs, I like to just get the .Net View objects of all VMs to start with.  So, instead of the first line being:

             

            Get-VM | Get-View | `

             

            make it something like:

             

            Get-View -ViewType VirtualMachine -Property Name,Guest.ToolsStatus,Config.Template | ?{$_.Config.Template -eq $false} | `

             

            The overall speed difference is remarkable.  I will refer to the original script as "method 0", and to the updated technique as "method 1".  I tested each method in a couple of environments, one with 400 VMs and one with 2600 VMs.  The amount of time to run each method in each environment:

             


            method 0 ('Get-VM | Get-View'...)method 1 ('Get-View'...)
            total run time for 400 VMs97 s1.2 s
            total run time for 2600 VMs654 s7 s

             

            Yes, that is 80 times faster and 93 times faster for the 400- and 2600 VM environments, respectively.

             

            So, while it might take a bit more typing up front to use only Get-View and to get only a few desired properties, that speed increase is well worth the effort.  I understand that people don't always kick off a script and then sit and wait for it to complete.  But, for the times that you do...

            1 person found this helpful
            • 3. Re: Script to find all  VM's with out dates/not installed tools.
              RvdNieuwendijk Virtuoso
              vExpertUser Moderators

              Good suggestion. "Get-View -ViewType VirtualMachine" is much faster than "Get-VM | Get-View".

               

              You inspired me to go for maximum speed. So I moved all the filtering also to the Get-View cmdlet. The next script is in my environment about 30% faster than the one you suggested. My first script took me 1 minute 50 seconds. Your script 1.624 seconds. And the next script 1.110 seconds in an environment with about 500 virtual machines..

               

               

              Get-View -ViewType VirtualMachine -Property Name,Guest.ToolsStatus -Filter @{
                "Config.Template"="False";"Guest.ToolsStatus"="toolsNotInstalled|toolsNotRunning|toolsOld"} | `
              Select-Object @{N="Name";E={$_.Name}},@{Name="ToolsStatus";E={$_.Guest.ToolsStatus}} | `
              Export-CSV -Path VmToolsStatus.csv -NoTypeInformation -UseCulture
              
              

               

               

              "Config.Template"="False" filters out templates so you only get virtual machines.

              "Guest.ToolsStatus"="toolsNotInstalled|toolsNotRunning|toolsOld" returns guests with ToolsStatus toolsNotInstalled or toolsNotRunning or toolsOld.

               

              With thanks to Eric Wannemacher for showing me how to use regular expressions in a Get-View filter in his blogpost: VMware PowerCLI and Get-View filters.

              • 4. Re: Script to find all  VM's with out dates/not installed tools.
                mattboren Master
                vExpert

                That's the stuff -- going for maximum speed -- yeah!

                 

                I had tried to use the -Filter parameter for Get-View when optimizing, but was not successful in coming up with a regex for _not_ matching "toolsOK".  Obviously that is an easy regex for matching, but I did not find how to make a regex for "match anything but" -- there were some convoluted ways that were not very reliable looking, but nothing solid.  Seems like that would be even just a bit faster.

                 

                But, then I missed putting the check-for-template piece into a Filter -- good catch.

                 

                I do wonder, though, about the ability to have a regex as described above.  That way, there would only be one string to focus on / worry about.  That is, there is no need to ensure that there are no other new values in the enumeration in question (VMware.Vim.VirtualMachineToolsStatus) that would need added to the "or" string in the Filter with a vertical bar.  One would rather just need to be sure that "toolsOK" is the valid value from the enumeration.


                Clean/fast code is one of the goals set for the PowerShellers group -- Glad to see the effort for the extra speed!

                • 5. Re: Script to find all  VM's with out dates/not installed tools.
                  RvdNieuwendijk Virtuoso
                  User ModeratorsvExpert

                  Hi Matt,

                   

                  at first I could not find the not match filter also. That's why I came with the vertical bars. This morning I did some more digging into regular expressions and found a solution for not match. You have to use (?! to invalidate the whole match. So the script now becomes:

                   

                  Get-View -ViewType VirtualMachine -Property Name,Guest.ToolsStatus -Filter @{
                    "Config.Template"="False";"Guest.ToolsStatus"="^(?!toolsOk$).*$" } | `
                  Select-Object Name,@{Name="ToolsStatus";E={$_.Guest.ToolsStatus}} | `
                  Export-CSV -Path VmToolsStatus.csv -NoTypeInformation -UseCulture
                  
                  

                   

                  A short explanation of the regular expression:

                   

                  ^            // the start of the string
                  (?!toolsOk$) // NOT followed by '
                  toolsOk' followed by the end of the string
                  .*           // matches any character (except new line chars) zero or more times
                  $            // followed by the end of the string

                   

                   

                  Regards, Robert

                   

                  I changed "Select-Object @{N="Name";E={$_.Name}},..." into "Select-Object Name,..." to make the script even faster.

                   

                  Message was edited by: RvdNieuwendijk

                  • 6. Re: Script to find all  VM's with out dates/not installed tools.
                    mattboren Master
                    vExpert

                    Hello, Robert-

                     

                    Yes, that is the regex pattern that I found in my looking, the one with which I was not very satisfied: "^(?!toolsOk$).*$"

                     

                    I had tested with it, and the full pattern worked, but when I trimmed it down to what I thought was still a valid "not match" pattern, it did not behave as I expected.  A bit more testing show more odd (to me) behavior.  So, I stopping going down that avenue.

                     

                    But, as you found that same pattern, I gave it another look.  Turns out the "(?!regex)" pattern is a "zero-width negative lookahead assertion" -- what a name!  After reading further about "lookaround processing", I came to understand a bit more what it is and how to use it (though I will definitely be checking the reference material at next use).

                     

                    And, it seems like that regex pattern can be cut down a little bit to something like, "^(?!toolsOK$)".  That leaves out the "any character, zero or more times" and the "end of line" anchor, which is a bit extraneous.  That was just for tightness/just-enough-ness of the expression, not for speed gain.  (I did test to see if it did make any speed difference, and in 200 runs with each regex for the filter, the times were nearly identical)

                     

                    Thanks for looking further into that!  Now I know a bit about the regex "lookaround" concept.  I can see that coming in handy now and again.

                    • 7. Re: Script to find all  VM's with out dates/not installed tools.
                      LucasAlbers Expert

                      What an amazingly useful tip, I never realized the speed difference. Thanks!.