Advanced vCenter

List and Disconnect vCenter Sessions

One of the first cmdlets people learn when starting out in PowerCLI is Connect-VIServer, this as you probably know allows you to connect to a vCenter server or a ESX/ESXi Host directly, this creates a session on the vCenter server until it has been disconnected using the Disconnect-VIServer cmdlet.

But who uses the Disconnect-VIServer cmdlet ? Come on truthfully, do you use it at the end of each script or PowerCLI session you use ?

This is obviously best practice but in my travels and from the code examples I have seen on the internet people seam to miss this out, on the face of it this is not an issue, it has “no impact” that you can see, but wait……

If you are in vCenter and go to the Sessions screen you will see that our sessions which were opened are now in an idle state:

image_thumb4

So why do we care ?

Did you know there is actually a limit on the amount of sessions which can connect to vCenter, this is set at 100 concurrent session, both Idle and active sessions count.

You would be surprised how quickly this can fill up in a corporate environment, especially if you have multiple scripts which run as scheduled tasks and do not disconnect correctly.

This was the case at a recent customer site, they needed a quick way out of this situation to enable them the time to go back and adjust the multiple scripts they had connecting and not disconnecting and the multiple staff they had who would RDP to a server and leave the vCenter client running and connected.

The following two PowerShell Advanced Functions were written to help with this situation:

List all sessions with PowerCLI

Function Get-ViSession {
<#
.SYNOPSIS
Lists vCenter Sessions.

.DESCRIPTION
Lists all connected vCenter Sessions.

.EXAMPLE
PS C:\> Get-VISession

.EXAMPLE
PS C:\> Get-VISession | Where { $_.IdleMinutes -gt 5 }
#>
$SessionMgr = Get-View $DefaultViserver.ExtensionData.Client.ServiceContent.SessionManager
$AllSessions = @()
$SessionMgr.SessionList | Foreach {
$Session = New-Object -TypeName PSObject -Property @{
Key = $_.Key
UserName = $_.UserName
FullName = $_.FullName
LoginTime = ($_.LoginTime).ToLocalTime()
LastActiveTime = ($_.LastActiveTime).ToLocalTime()

}
If ($_.Key -eq $SessionMgr.CurrentSession.Key) {
$Session | Add-Member -MemberType NoteProperty -Name Status -Value “Current Session”
} Else {
$Session | Add-Member -MemberType NoteProperty -Name Status -Value “Idle”
}
$Session | Add-Member -MemberType NoteProperty -Name IdleMinutes -Value ([Math]::Round(((Get-Date) – ($_.LastActiveTime).ToLocalTime()).TotalMinutes))
$AllSessions += $Session
}
$AllSessions
}

 

When this function is run it will give you a list of the connected sessions and various useful properties:

SNAGHTML366d1b1_thumb2

This can obviously be filtered using the standard PowerShell cmdlets to list any sessions which have been idle for over 30 minutes:

SNAGHTML367dc9a_thumb2

A further function can be used to take the input from Get-VISession and disconnect these sessions where needed:

Disconnect sessions with PowerCLI

Function Disconnect-ViSession {
<#
.SYNOPSIS
Disconnects a connected vCenter Session.

.DESCRIPTION
Disconnects a open connected vCenter Session.

.PARAMETER  SessionList
A session or a list of sessions to disconnect.

.EXAMPLE
PS C:\> Get-VISession | Where { $_.IdleMinutes -gt 5 } | Disconnect-ViSession

.EXAMPLE
PS C:\> Get-VISession | Where { $_.Username -eq “User19” } | Disconnect-ViSession
#>
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
$SessionList
)
Process {
$SessionMgr = Get-View $DefaultViserver.ExtensionData.Client.ServiceContent.SessionManager
$SessionList | Foreach {
Write “Disconnecting Session for $($_.Username) which has been active since $($_.LoginTime)”
$SessionMgr.TerminateSession($_.Key)
}
}
}

The following example shows how to use these functions to disconnect any sessions with over 30 minutes of idle time:

SNAGHTML36c8019_thumb2

Both of these functions show that even if there is not a built in cmdlet for a certain feature in PowerCLI there is always an easy way to create your own cmdlet like functions to work the way you need them.

Alan Renouf

Technical Marketing

Post updated: 3/6/2015 to correct number of supported sessions to 100.

Comments

17 comments have been added so far

  1. I’m looking for a possibility to get to know the source IPs where the clients are connecting from. Any idea?
    BTW: Does that function also run on 4.1U1? I have some trouble…

  2. I made a function that will disconnect an old session when I connect to a new one. Throughout the day I’ll connect to at least a few different vcenters in 2-3 different powershell console windows. We have one vcenter on a different AD domain so I have the function prompt for a login on that one instead for the “connect with default, fail, log a failed login attempt, prompt for credentials” sequence. It’s faster and keeps failed logins out of our vcheck report.
    function cvi {
    param($vcenter)
    if ($global:DefaultVIServers) { Disconnect-VIServer $global:DefaultVIServers -Confirm:$false }
    Get-PowerCLIConfiguration
    if ((Get-PowerCLIConfiguration).DefaultVIServerMode -ne “Single”) { Set-PowerCLIConfiguration -DefaultVIServerMode Single -Confirm:$false }
    If ($vcenter -match “vcenterxxyyzz”)
    { Connect-VIServer $vcenter -User “domain\user” | Select-Object Uid,Version,User }
    Else
    { Connect-VIServer $vcenter | Select-Object Uid,Version,User }
    }

  3. —-It is set at 500 concurrent session—

    This is mentioned above in the blog. Can you please tell me where is this setting configured in VCenter.? Does this apply in 5.0 U2 ? Is there a way we can increase this to 1000?

    Thanks,
    G Kapoor

  4. How to use the programming language?
    Because I type Get-vission is show up the below ?
    無法辨識 ‘Get-VISession’ 詞彙是否為 Cmdlet、函數、指令檔或可執行程式的名稱。請檢查名稱拼字是否正確,如果包含路徑的話,請確認路徑是否正確,
    然後再試一次。
    位於 行:1 字元:14
    + Get-VISession <<<< | Where { $_.IdleMinutes -gt 5 }
    + CategoryInfo : ObjectNotFound: (Get-VISession:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

  5. Three quick observations:

    One, where you have…

    Get-View $DefaultViserver...

    … I think you have to have…

    Get-View $global:DefaultVIServer...

    … with the $global added, correct? That made it start working for me. Either that or you’re setting that variable up in some sort of parent scope you don’t have here, since you’re not taking params into Get-ViSession.

    Two, I’ve never had anything returned in $SessionMgr.SessionList. I’ve noticed that $SessionMgr.CurrentSession has the same object model, however, so I’m using that when SessionList -eq $null (which, again, is *always* for me).

    Last, if nothing is connected, $global.DefaultVIServer dies, so I need to protect that with…
    if ((Test-Path Variable:global:DefaultVIServer) -and $global:DefaultVIServer -ne $null)

    But otherwise a very helpful thing to do. Makes managing connections much easier. Thanks!

  6. Hi there,

    first i have to say i’m new to powercli and powershell.

    when i put this funktions above into a script, i can call the Get-VISession at the end.

    the output is all sesions, as expected.

    the crazy thing is, that i can not use the
    Get-VISession | Where { $_.IdleMinutes -gt 5 }

    there is no output, but i have idle sessions.
    for sure if that not works i cannot use the Get-VISession | Where { $_.IdleMinutes -gt 5 } | Disconnect-ViSession

    can you give a hint?

    regards chris

  7. I have improved the original script, now it works with multiple connected servers, shows the IP of the logged on user, shows the server name of the session, and will skip sessions created by extensions:

    Function Get-ViSession {
    Get-VISession

    .EXAMPLE
    PS C:\> Get-VISession | Where { $_.IdleMinutes -gt 5 }
    #>
    $global:DefaultVIServers | ForEach {
    $VIServer = $_.Name
    $SessionMgr = Get-View -id SessionManager -Server $VIServer
    $AllSessions = @()
    $SessionMgr.SessionList | ? UserName -notlike '*vpxd-extension*' | Foreach {
    $Session = New-Object -TypeName PSObject -Property @{
    Server = $VIServer
    Key = $_.Key
    UserName = $_.UserName
    FullName = $_.FullName
    LoginTime = ($_.LoginTime).ToLocalTime()
    LastActiveTime = ($_.LastActiveTime).ToLocalTime()
    IPAddress = $_.IPAddress
    }
    If ($_.Key -eq $SessionMgr.CurrentSession.Key) {
    $Session | Add-Member -MemberType NoteProperty -Name Status -Value "Current Session"
    } Else {
    $Session | Add-Member -MemberType NoteProperty -Name Status -Value "Idle"
    }
    $Session | Add-Member -MemberType NoteProperty -Name IdleMinutes -Value ([Math]::Round(((Get-Date) - ($_.LastActiveTime).ToLocalTime()).TotalMinutes))
    $AllSessions += $Session
    }
    $AllSessions
    }
    }

    1. Sorry the comments got messed up when pasting:

      Function Get-ViSession {
      <#
      .SYNOPSIS
      Lists vCenter Sessions.

      .DESCRIPTION
      Lists all connected vCenter Sessions.

      .EXAMPLE
      PS C:\> Get-VISession

      .EXAMPLE
      PS C:\> Get-VISession | Where { $_.IdleMinutes -gt 5 }
      #>
      $global:DefaultVIServers | ForEach {
      $VIServer = $_.Name
      $SessionMgr = Get-View -id SessionManager -Server $VIServer
      $AllSessions = @()
      $SessionMgr.SessionList | ? UserName -notlike '*vpxd-extension*' | Foreach {
      $Session = New-Object -TypeName PSObject -Property @{
      Server = $VIServer
      Key = $_.Key
      UserName = $_.UserName
      FullName = $_.FullName
      LoginTime = ($_.LoginTime).ToLocalTime()
      LastActiveTime = ($_.LastActiveTime).ToLocalTime()
      IPAddress = $_.IPAddress
      }
      If ($_.Key -eq $SessionMgr.CurrentSession.Key) {
      $Session | Add-Member -MemberType NoteProperty -Name Status -Value "Current Session"
      } Else {
      $Session | Add-Member -MemberType NoteProperty -Name Status -Value "Idle"
      }
      $Session | Add-Member -MemberType NoteProperty -Name IdleMinutes -Value ([Math]::Round(((Get-Date) - ($_.LastActiveTime).ToLocalTime()).TotalMinutes))
      $AllSessions += $Session
      }
      $AllSessions
      }
      }

  8. Thanks for the script, but looks like it fails to kill the webclient sessions. Even when I try from the webclient to terminate other webclient sessions they just reappear. Can somebody please advise.

  9. I was using this script successfully in older versions of PowerCLI.
    Does the same works in PowerCLI 6.5 ?

  10. This can be done in one line:

    If($DefaultViserver.Count -gt 0){$DefaultViserver | Disconnect-VIServer -confirm:$false }

  11. This does not work for me, receiving:

    Exception calling “TerminateSession” with “1” argument(s): “The object or item referred to could not be found.”
    At line:27 char:1
    + $SessionMgr.TerminateSession($_.Key)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : VimException

    When trying to disconnect some sessions.
    Any ideas ?

Leave a Reply

Your email address will not be published. Required fields are marked *