Home > event, PowerCLI, PowerShell, Session Manager > Get complete vCenter session info

Get complete vCenter session info

January 17th, 2012 Leave a comment Go to comments

There was an interesting thread in the PowerCLI Community today. It raised the question how one could report on the current vCenter sessions, including the IP address or hostname from where the session was started.

Unfortunately the SessionManager doesn’t hold any information from where the session was started.

But there are other ways of finding that information. The UserLoginSessionEvent object has a property, called ipAddress, that has the information we’re after.

Btw if you are only interested in looking for idle sessions, independent from which host they were started, there is a great post, called List and Disconnect vCenter Sessions on the PowerCLI blog.

Update May 4th 2012: function updated to handle multiple vCenter connections.

The script

function Get-VISessionInfo{
<#
.SYNOPSIS  Retrieve vCenter session information
.DESCRIPTION The function will retrieve the open vCenter
  session, including the IP address and hostname from where
  the session was started
.NOTES  Author:  Luc Dekens
.PARAMETER AllowedDifference
  The timestamps from the Session Manager entries and the
  event objects can sometimes differ, depending on the vCenter
  activity. The default is 1 second, but this can be changed
  with this parameter. The unit for this parameter is seconds.
.EXAMPLE
  PS> Get-VISessionInfo
#>

  param(
  [CmdletBinding()]
  [int]$AllowedDifference = 1
  )

  process{
    if((Get-PowerCLIConfiguration).DefaultVIServerMode -eq "Multiple"){
      $vcenter = $defaultVIServers
    }
    else{
      $vcenter = $defaultVIServers[0]
    }

    foreach($vc in $vcenter){
      $sessMgr = Get-View SessionManager -Server $vc
      $oldest = ($sessMgr.SessionList | Sort-Object -Property LoginTime | Select -First 1).LoginTime
      $users = $sessMgr.SessionList | %{$_.UserName}
      $events = Get-VIEvent -MaxSamples ([int]::MaxValue) -Start $oldest.AddHours(-1) -Server $vc |
      where {$_ -is [VMware.Vim.UserLoginSessionEvent] -and $users -contains $_.UserName} |
      Sort-Object -Property CreatedTime

      $allowedDiffTS = New-TimeSpan -Seconds $AllowedDifference

      foreach($session in $sessMgr.SessionList){
        $events |
        where {[math]::Abs(($session.LoginTime.ToLocalTime() - $_.CreatedTime).Ticks) -lt $allowedDiffTS.Ticks -and
          $users -contains $_.UserName} | %{
          New-Object PSObject -Property @{
            vCenter = $vc.Name
            "Session login" = $session.LoginTime
            UserName = $_.UserName
            IPAddress = $_.IPAddress
            Hostname = [System.Net.Dns]::GetHostEntry($_.IPAddress).HostName
          }
        }
      }
    }
  }
}

Annotations

Line 23-28: If the PowerCLI session is configured in “Multiple” mode, the function will loop through all connected vCenters. The Get-PowerCLIConfiguration cmdlet is used to retrieve the active mode.

Line 32: The script will look for the session with the oldest login time. This will allow us to limit the number of events that need to be retrieved.

Line 33: Besides the timestamps, the script will also check if the username that appears in an user session login event, is one of the users that has an open vCenter session.

Line 34-36: We retrieve the UserLoginSessionEvent for users that have an open vCenter session.

Line 38: The time difference we allow between the timestamp in the session and the corresponding UserLoginSessionEvent is converted to a TimeSpan object.

Line 42: To link a vCenter session to a UserLoginSessionEvent the script calculates the time difference between the timestamps in the UserLoginSessionEvent and the session object from the SessionManager. If the absolute time difference falls below the accepted time difference ($AllowedDifference), the event is linked to the session.

Line 44-49: The result is placed in the pipeline

Line 45: The output contains the name of the vCenter where the session was found.

Line 49: The script converts the IP address to the hostname with the GetHostEntry method.

Sample usage

The function is rather simple in use.


Get-VISessionInfo

And the result looks something like this.

Enjoy!

  1. Alok
    February 25th, 2016 at 22:15 | #1

    Hello Luc,

    Is there a script I can use to audit — who, when and what PowerCLI commands did the users ran on a Vcenter server and export it to an excel file or get a email copy to myself

    • February 25th, 2016 at 23:54 | #2

      Hi Alok,
      No, I’m afraid there is no central logging of the PowerCLI cmdlets.
      But you can check the Task and Events, they will show you the actions resulting from the PowerCLI cmdlets.
      There are several example on this site on how you can use events.

  2. P3OPL3SH3RO
    February 3rd, 2016 at 23:34 | #3

    Should this work in 5.5U3? I am trying to run this and I get no output, not error or anything either.

    • February 4th, 2016 at 07:13 | #4

      Yes, that should work in 5.5U3.
      Just tried it, and I seem to be getting the expected output.
      Did you try using the AllowedDifference parameter ?
      The default is a one second difference between the session timestamp and the corresponding event timestamp.
      In some environments this might require a higher value. Try for example running as

      Get-VISessionInfo -AllowedDifference 10

      This will look for the corresponding event within a +/- 10 second interval around the session start time.

      • P3OPL3SH3RO
        February 4th, 2016 at 13:24 | #5

        Tried changing it but sill nothing. All I did was copy your script, connect to my virtual center server, connect to my server via PowerCLI 6.0 Release 2 and execute the script. Am I missing something else?

        • February 4th, 2016 at 14:07 | #6

          Just to make sure, you did call the function ?
          The script, if you copied my code, just contains the function, you have to call it, to execute it.
          See the Sample Usage section

          • P3OPL3SH3RO
            February 4th, 2016 at 16:17 | #7

            I guess I am not following here. If I type Get-VISessionInfo it is not recognized as the name of a cmdlet. Is this something I need to edit in the code so that I have a runable script?

          • P3OPL3SH3RO
            February 4th, 2016 at 16:29 | #8

            I found an old post from you in regards to dot-sourcing the ps1 file and then calling the function. I think I have it now, getting errors back on some “GetHostEntry” not found but its running. Thanks!

            • February 4th, 2016 at 18:16 | #9

              Great!
              Let me hear if other issues should pop up

  3. roshan
    September 7th, 2015 at 01:45 | #10

    any chance if the script can be ported to a plugin for vchecks?

  4. s1c
    February 10th, 2014 at 10:18 | #11

    Hi

    The idea of this script is simple awesome!
    But it doesn’t work for me :/
    Im running that script but there’s no any output (nor error). I don’t have problem with running other cmdlets. For example I run this and got some users output without any problems:
    ——-code——
    $svcRef = new-object VMware.Vim.ManagedObjectReference
    $svcRef.Type = “ServiceInstance”
    $svcRef.Value = “ServiceInstance”
    $serviceInstance = get-view $svcRef
    $sessMgr = get-view $serviceInstance.Content.sessionManager
    foreach ($sess in $sessMgr.SessionList){if (($sess.LastActiveTime).addminutes(60) -lt (Get-Date)){write “$($sess.UserName)”}
    }
    ——-code——

  5. John Zed
    October 9th, 2013 at 03:24 | #12

    Hi Luc

    Great function, very usefull
    Do you think you could add the block Jonathan Medd added in the comments ?
    i just don’t understand where to put it.

    thanks in advance

  6. Chris Wilson
    August 22nd, 2013 at 14:33 | #13

    Is it possible to get the vcenter version and build number when connecting to multiple vcenters?

  7. Arvinth
    July 2nd, 2013 at 09:21 | #14

    hey Luc,

    I am trying to get the history of Vcenter users login/logouts from January2013 to till date & when i execute the below script it returns nothing.

    will be helpful if you could find the mistake in the below script

    Get-VIEvent -start 03/06/2013 -finish 02/07/2013 | ?{($_ -is [VMware.Vim.UserLoginSessionEvent]) -or ($_ -is [VMware.Vim.UserLogoutSessionEvent])} | %{
    if ($_ -is [VMware.Vim.UserLoginSessionEvent]) {$strLoginOrLogout = “logged in”; $strSourceIP = $_.IpAddress} ## end if
    else {$strLoginOrLogout = “logged out”; $strSourceIP = $null}
    New-Object -TypeName PSObject -Property @{
    UserName = $_.UserName
    SourceIP = $strSourceIP
    Time = $_.CreatedTime
    Action = $strLoginOrLogout
    } ## end new-object
    } | Select UserName,SourceIP,Time,Action

    • admin
      July 2nd, 2013 at 10:38 | #15

      Hi Arvinth,
      Can you try changing that 1st line into

      Get-VIEvent -start (Get-Date 03/06/2013) -finish (Get-Date 02/07/2013)

      The function expects DateTime objects on the Start and Finish parameters, and I think it sees [string] objects when called the way you did it.

  8. June 24th, 2013 at 11:44 | #16

    Thanks for this, very useful 🙂

    If you add the following, then you also get the type of client connection, e.g. vSphere Client, PowerCLI etc….

    $PowerShell2EscapeString = [regex]::Escape(“Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0”)
    $PowerShell3EscapeString = [regex]::Escape(“Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0”)

    switch -regex ($_.UserAgent)
    {
    “VMware VI Client” {$Agent = “vSphere Client”; break}
    “VMware vim-java 1.0” {$Agent = “vSphere WebClient”; break}
    $PowerShell2EscapeString {$Agent = “PowerCLI (PS2)” ;break}
    $PowerShell3EscapeString {$Agent = “PowerCLI (PS3)” ;break}
    “Java/1.6.0_20” {$Agent = “VI Java”; break}
    “VI Perl” {$Agent = “vSphere SDK for Perl”; break}
    Default {$Agent = “Unable to determine the agent type”}
    }

    New-Object PSObject -Property @{

    vCenter = $vc.Name
    “Session login” = $session.LoginTime
    UserName = $_.UserName
    IPAddress = $_.IPAddress
    Hostname = [System.Net.Dns]::GetHostEntry($_.IPAddress).HostName
    Agent = $Agent
    }

    Note: the webclient IP is that of the server running the WebClient service, not the IP of the user running the webclient

    Thanks to the below for helping to decode them:

    http://www.virtuallyghetto.com/2010/12/how-to-identify-origin-of-vsphere-login.html

  9. amit
    May 1st, 2013 at 15:19 | #21

    how i create VISessionInfo olease to view ip and hostname?

  10. Paul Anderson
    May 24th, 2012 at 17:05 | #22

    I’m getting similar errors to Wayne:

    You cannot call a method on a null-valued expression.
    At H:\Scripts\VMware PowerCLI\Get-VISessionInfo.ps1:34 char:82
    + $events = Get-VIEvent -MaxSamples ([int]::MaxValue) -Start $oldest.AddHours <<<< (-1) -Server $vc |
    + CategoryInfo : InvalidOperation: (AddHours:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At H:\Scripts\VMware PowerCLI\Get-VISessionInfo.ps1:42 char:59
    + where {[math]::Abs(($session.LoginTime.ToLocalTime <<<< () – $_.CreatedTime).Ticks) -lt $allowedDiffTS.Ticks -and
    + CategoryInfo : InvalidOperation: (ToLocalTime:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    I don't know why $oldest and $session.LoginTime are NULL. LucD, can you please help ?

    PS: If this is a duplicate post, sorry, my last post appeared to fail.

  11. Pedro Magalhaes
    May 4th, 2012 at 12:50 | #23

    Please check if you are connected to more than one vcenter server

    • May 4th, 2012 at 17:31 | #24

      @Pedro, I have updated the function to handle multiple vCenter connections.

  12. chris
    March 14th, 2012 at 16:04 | #25

    45 lines of code to get an IP address – really? This looks like a great script but having to write 45 lines of code to get to this tells me something was left out in the design process.

    • March 14th, 2012 at 17:35 | #26

      Hi Chris, there are 14 lines of comments in there as well.
      But seriously, I agree with you, the script uses another source (Events) to find the IP addresses which should have been there in the first place.
      There is definitely room for improvement 🙂

  13. Tom
    March 13th, 2012 at 07:36 | #27

    @Wayne
    I got the same message when I tried running it, anyone have any hot tips as to what I am doing wrong?

  14. Wayne
    February 8th, 2012 at 22:45 | #28

    Tried running the script I received a couple of errors….

    You cannot call a method on a null-valued expression.
    At P:\Powershell\Vmware\Get-vcenter-sessions\get-VISessionInfo.ps1:26 char:80
    + $events = Get-VIEvent -MaxSamples ([int]::MaxValue) -Start $oldest.AddHours <<<< (-1) |
    + CategoryInfo : InvalidOperation: (AddHours:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At P:\Powershell\Vmware\Get-vcenter-sessions\get-VISessionInfo.ps1:34 char:57
    + where {[math]::Abs(($session.LoginTime.ToLocalTime <<<< () – $_.CreatedTime).Ticks) -lt $allowedDiffTS.Ticks -and
    + CategoryInfo : InvalidOperation: (ToLocalTime:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  15. Kyle Hanson
    February 1st, 2012 at 00:33 | #29

    Nice script. 🙂

    Good to have a script like this ready for troubleshooting connection issues.

  1. No trackbacks yet.