<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[[Bug?] Load Balancer: Performance mode fails to power on hosts previously shut down by Density mode]]></title><description><![CDATA[<h1>[Bug?] Load Balancer: Performance mode fails to power on hosts previously shut down by Density mode</h1>
<p dir="auto">Hi everyone,</p>
<p dir="auto">I'm experiencing a possible bug with the <strong>Xen Orchestra Load Balancer plugin</strong> when switching from <strong>Density</strong> to <strong>Performance</strong> mode.</p>
<p dir="auto">Density successfully consolidates VMs and shuts down an unused host, but switching back to Performance does not automatically power that host on, even though Wake-on-LAN is correctly configured and works manually.</p>
<p dir="auto">After investigating the source code, I suspect that the host filtering logic prevents Performance mode from detecting hosts that were disabled during shutdown.</p>
<h2>Environment</h2>
<ul>
<li><strong>Xen Orchestra:</strong> Built from source</li>
<li><strong>Build:</strong> (November 10, 2026) <code>Xen Orchestra, commit 03e93</code> | <code>Master, commit 83c3e</code></li>
<li><strong>Plugin:</strong> <code>xo-server-load-balancer</code></li>
<li><strong>Storage:</strong> Shared storage, live VM migrations working</li>
<li><strong>Power-on method:</strong> Wake-on-LAN</li>
</ul>
<p dir="auto">The pool contains three hosts:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Host</th>
<th>Role</th>
<th>Load Balancer configuration</th>
</tr>
</thead>
<tbody>
<tr>
<td>XCPNG1</td>
<td>Additional host</td>
<td>Excluded from the plan</td>
</tr>
<tr>
<td>XCPNG2</td>
<td>Pool Master</td>
<td>Always running</td>
</tr>
<tr>
<td>XCPNG3</td>
<td>Secondary host</td>
<td>Managed by Load Balancer</td>
</tr>
</tbody>
</table>
<p dir="auto">Xen Orchestra itself runs as a VM on the Pool Master (XCPNG2).</p>
<h2>Steps to reproduce</h2>
<ol>
<li>Start XCPNG2 and XCPNG3.</li>
<li>Set the Load Balancer plan to <strong>Performance</strong>.</li>
<li>Plugin distributes VMs between both hosts (approximately 50/50).</li>
<li>Switch the plan to <strong>Density</strong>.</li>
<li>Density successfully migrates the VMs from XCPNG3 to XCPNG2 and automatically shuts down XCPNG3.</li>
<li>Switch the same plan back to <strong>Performance</strong>.</li>
<li>Save the configuration and wait for multiple Load Balancer execution cycles.</li>
</ol>
<h3>Expected behavior</h3>
<p dir="auto">According to the <a href="https://docs.xen-orchestra.com/manage-your-infrastructure/load_balancing" target="_blank" rel="noopener noreferrer nofollow ugc">official Xen Orchestra Load Balancing documentation</a>, Performance mode should automatically power on halted hosts when a power-on mode is configured.</p>
<p dir="auto">XCPNG3 should therefore power on automatically.</p>
<h3>Actual behavior</h3>
<p dir="auto">XCPNG3 remains powered off.</p>
<p dir="auto">No automatic power-on occurs.</p>
<p dir="auto">However, clicking the <strong>Play / Power on</strong> button for XCPNG3 in the Xen Orchestra UI successfully starts the host.</p>
<p dir="auto">The issue does not appear to be related to Wake-on-LAN connectivity.</p>
<h2>Load Balancer configuration</h2>
<ul>
<li>Mode: <code>Performance</code></li>
<li>Performance behavior: <code>Conservative</code></li>
<li>CPU critical threshold: <code>90%</code></li>
<li>RAM free critical threshold: <code>10000 MB</code></li>
<li>Migration cooldown: <code>1 minute</code></li>
<li>Maximum concurrent migrations: <code>1</code></li>
<li>Excluded hosts: <code>XCPNG1</code></li>
</ul>
<p dir="auto">The same pool and plan work correctly in Density mode.</p>
<h2>Investigation</h2>
<h3>1. XAPI power-on mode is configured</h3>
<p dir="auto">Running the following command on the Pool Master:</p>
<pre><code class="language-bash">xe host-list params=name-label,uuid,power-on-mode
</code></pre>
<p dir="auto">Returns:</p>
<pre><code class="language-text">XCPNG3
power-on-mode: wake-on-lan

XCPNG1
power-on-mode: wake-on-lan

XCPNG2
power-on-mode: wake-on-lan
</code></pre>
<h3>2. XCPNG3 is disabled after Density shuts it down</h3>
<p dir="auto">Running:</p>
<pre><code class="language-bash">xe host-list \
  uuid=dd2cec0b-7849-412e-a040-e2826c35c6cc \
  params=name-label,enabled,power-on-mode
</code></pre>
<p dir="auto">Returns:</p>
<pre><code class="language-text">name-label    : XCPNG3
enabled       : false
power-on-mode : wake-on-lan
</code></pre>
<h3>3. Performance mode attempts to power on halted hosts</h3>
<p dir="auto">In:</p>
<p dir="auto"><code>packages/xo-server-load-balancer/src/performance-plan.js</code></p>
<p dir="auto">The <code>execute()</code> method begins with:</p>
<pre><code class="language-javascript">async execute() {
  // Try to power on a hosts set.
  try {
    await Promise.all(
      filter(
        this._getHosts({ powerState: 'Halted' }),
        host =&gt; host.powerOnMode !== ''
      ).map(host =&gt; {
        const { id } = host
        return this.xo.getXapi(id).powerOnHost(id)
      })
    )
  } catch (error) {
    console.error(error)
  }
}
</code></pre>
<p dir="auto">This suggests that Performance should attempt to power on halted hosts independently of CPU/RAM thresholds or migration cooldown.</p>
<h3>4. Potential issue in <code>_getHosts()</code></h3>
<p dir="auto">In:</p>
<p dir="auto"><code>packages/xo-server-load-balancer/src/plan.js</code></p>
<p dir="auto">Lines 256–265:</p>
<pre><code class="language-javascript">_getHosts({ powerState = 'Running' } = {}) {
  return filter(
    this.xo.getObjects(),
    object =&gt;
      object.type === 'host' &amp;&amp;
      includes(this._poolIds, object.$poolId) &amp;&amp;
      object.power_state === powerState &amp;&amp;
      !includes(this._excludedHosts, object.id) &amp;&amp;
      object.enabled === true
  )
}
</code></pre>
<pre><code class="language-javascript">object.enabled === true
</code></pre>
<p dir="auto">If a halted host has <code>enabled: false</code>, <code>_getHosts({ powerState: 'Halted' })</code> appears to exclude it before Performance can call <code>powerOnHost()</code>.</p>
<h3>5. Density uses <code>shutdownHost()</code></h3>
<p dir="auto">In:</p>
<p dir="auto"><code>packages/xo-server-load-balancer/src/density-plan.js</code></p>
<pre><code class="language-javascript">debug(`Shutdown Host (${fmtSrcHost}).`)

try {
  await xapiSrc.shutdownHost(srcHost.id)
} catch (error) {
  debug(`Unable to shutdown Host (${fmtSrcHost}).`, { error })
}
</code></pre>
<p dir="auto">The underlying implementation in:</p>
<p dir="auto"><code>packages/xo-server/src/xapi/index.mjs</code></p>
<p dir="auto">Contains:</p>
<pre><code class="language-javascript">async shutdownHost(hostId, { force = false, bypassEvacuate = false } = {}) {
  const host = this.getObject(hostId)
  if (bypassEvacuate) {
    await this.call('host.disable', host.$ref)
  } else {
    await this.clearHost(host, force)
  }
  await this.callAsync('host.shutdown', host.$ref)
}
</code></pre>
<p dir="auto">This is consistent with the observation that XCPNG3 ends up with <code>enabled: false</code> after being shut down by Density.</p>
<h2>Suspected root cause</h2>
<p dir="auto">My hypothesis is:</p>
<ol>
<li>Density evacuates XCPNG3.</li>
<li>Density calls <code>shutdownHost()</code>.</li>
<li>XCPNG3 becomes halted and disabled (<code>enabled: false</code>).</li>
<li>Performance calls <code>_getHosts({ powerState: 'Halted' })</code>.</li>
<li><code>_getHosts()</code> filters out XCPNG3 because <code>enabled !== true</code>.</li>
<li><code>powerOnHost()</code> is never called for XCPNG3.</li>
</ol>
<p dir="auto">This would explain why manual power-on through the Xen Orchestra UI works while automatic power-on through the Load Balancer does not.</p>
<h2>Possible fix</h2>
<p dir="auto">Would it make sense to allow disabled hosts to be returned by <code>_getHosts()</code> <strong>only when searching for halted hosts to power on</strong>?</p>
<p dir="auto">For example, the condition:</p>
<pre><code class="language-javascript">object.enabled === true
</code></pre>
<p dir="auto">could potentially become:</p>
<pre><code class="language-javascript">(powerState === 'Halted' || object.enabled === true)
</code></pre>
<h2>Questions</h2>
<ol>
<li>Is this a known issue in the current Load Balancer implementation?</li>
<li>Is <code>enabled: false</code> expected after Density shuts down a host?</li>
<li>Should Performance be able to restart a host in this state?</li>
<li>Is the <code>enabled === true</code> filter intentional for halted hosts?</li>
<li>Is there an existing workaround or an upstream fix?</li>
</ol>
<p dir="auto">The goal is to use Density at night to consolidate VMs and shut down unused hosts, then switch to Performance during the day to bring those hosts back online automatically.</p>
<p dir="auto">Thanks in advance for any insights!</p>
]]></description><link>https://xcp-ng.org/forum/topic/12575/bug-load-balancer-performance-mode-fails-to-power-on-hosts-previously-shut-down-by-density-mode</link><generator>RSS for Node</generator><lastBuildDate>Wed, 11 Nov 2026 16:11:06 GMT</lastBuildDate><atom:link href="https://xcp-ng.org/forum/topic/12575.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 11 Nov 2026 14:14:33 GMT</pubDate><ttl>60</ttl></channel></rss>