Skip to content

🐛 Vsphere idle connections fix#6583

Draft
AdamVB wants to merge 2 commits intomainfrom
vsphere-idle-fix
Draft

🐛 Vsphere idle connections fix#6583
AdamVB wants to merge 2 commits intomainfrom
vsphere-idle-fix

Conversation

@AdamVB
Copy link
Copy Markdown

@AdamVB AdamVB commented Feb 6, 2026

Root Cause: Two Issues Causing Idle Connection Buildup

Issue 1 (Critical): Missing ParentConnectionId in discovered assets

Files: providers/vsphere/resources/discovery.go:125,170

When the vSphere provider discovers child assets (ESXi hosts, VMs), it clones the parent config but never sets ParentConnectionId:

// Line 125 (hosts) and 170 (VMs) — current code:
clonedConfig := conn.Conf.Clone(inventory.WithoutDiscovery())

Compare with the k8s provider, which does this correctly (providers/k8s/resources/discovery.go):

invConfig.Clone(inventory.WithoutDiscovery(),
    inventory.WithParentConnectionId(invConfig.Id))

What happens without ParentConnectionId:

  1. cnquery connects to vSphere API → 1 govmomi.Client session created
  2. Discovery finds N hosts + M VMs → returns them as child assets
  3. The runtime scans each child asset by calling Connect() again
  4. Each Connect()NewVsphereConnection()govmomi.NewClient() → a brand new authenticated vSphere session
  5. Result: 1 + N + M sessions instead of just 1

Example: For a vSphere environment with 100 VMs and 10 hosts, that's 111 connections instead of 1.

How ParentConnectionId would fix it:

When set, plugin.Service.AddRuntime() (providers-sdk/v1/plugin/service.go:73-81) detects the parent ID, retrieves the parent runtime, and shares its resources — no new govmomi.Client is created.


Issue 2 (High): Missing Close() / session logout

File: providers/vsphere/connection/connection.go

VsphereConnection does not implement the plugin.Closer interface. When disconnect happens, doDisconnect() (providers-sdk/v1/plugin/service.go:157) checks:

if closer, ok := runtime.Connection.(Closer); ok {
    closer.Close()  // Never called — VsphereConnection doesn't implement Closer
}

The govmomi.Client is never logged out (client.Logout(ctx)), so even after scanning completes, the sessions remain open on the vSphere server until they time out.


Summary

Issue Missing WithParentConnectionId No Close() method / session logout
File discovery.go:125,170 connection.go
Impact Creates N+1 connections instead of 1 Sessions never closed, remain idle on server

Proposed Fix

  1. Add WithParentConnectionId to discovery cloning:

    clonedConfig := conn.Conf.Clone(
        inventory.WithoutDiscovery(),
        inventory.WithParentConnectionId(conn.Conf.Id))
    

    Apply to both Clone() calls in discovery.go:125,170

  2. Implement Close() method in VsphereConnection:

    func (c *VsphereConnection) Close() error {
        return c.client.Logout(context.Background())
    }
    

    This satisfies the plugin.Closer interface and ensures proper session cleanup.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 6, 2026

Test Results

4 967 tests  ±0   4 963 ✅ ±0   2m 21s ⏱️ -1s
  418 suites ±0       4 💤 ±0 
   31 files   ±0       0 ❌ ±0 

Results for commit 55fc754. ± Comparison against base commit bda4f63.

@tas50 tas50 changed the title Vsphere idle connections fix 🐛 Vsphere idle connections fix Feb 6, 2026
@tas50
Copy link
Copy Markdown
Member

tas50 commented Mar 3, 2026

/review

Copy link
Copy Markdown

@mondoo-code-review mondoo-code-review bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes vSphere connection leak: child assets now share the parent connection and sessions are properly logged out on disconnect.


func (c *VsphereConnection) Close() {
if c.client != nil {
c.client.Logout(context.Background())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 suggestionLogout returns an error that is silently discarded. Consider logging it so failed logouts are visible in debug output:

if err := c.client.Logout(context.Background()); err != nil {
	log.Debug().Err(err).Msg("failed to logout vsphere session")
}

Not a correctness issue (the Closer interface is Close() with no return), but helpful for diagnosing connection-cleanup failures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants