Skip to content

Commit 600142d

Browse files
committed
Properly calculate a cluster's free memory
cluster free memory in the vSphere CPI uses "effective_memory" [0] defined as follows [1]: Effective memory resources (in MB) available to run virtual machines. This is the aggregated effective resource level from all running hosts. Hosts that are in maintenance mode or are unresponsive are not counted. Resources used by the VMware Service Console are not included in the aggregate. This value represents the amount of resources available for the root resource pool for running virtual machines. This sounds like it's "available free memory", but it's not. It's total effective memory that a cluster could give to VMs. This is the wrong metric to use for "free memory" as it does not vary based on the memory consumption for the cluster. This commit changes the calculation to subtract from the effective memory the memory demand, "Sum of memory demand of all the powered-on VMs in the cluster" [2]. The new metric appears to more closely reflect vCenter's reporting of memory. For example, on https://vcenter-80.nono.io: the effective memory 490 GiB effective memory, old, wrong calculation - 86 GiB demand memory ------- 404 GiB new, better calculation 420 GiB vCenter's reporting of "Available Reservation" Note that although this new calculation of memory is more "truthful", measuring memory is nuanced: vSphere has 3 different metrics for memory use (memDemandMB, memEntitledMB, memReservationMB). Furthermore, on vCenter's cluster's summary page, the "free" memory (e.g. 184 GiB) doesn't dovetail with _any_ of the available metrics, nor any combination thereof. Drive-by: - I changed `VimSdk::Vim::ComputeResource::Summary` → `VimSdk::Vim::ClusterComputeResource::Summary` in our tests because that was the object reflected in the vSphere MOB browser (we were instance-doubling the wrong object). [0] https://github.com/cloudfoundry/bosh-vsphere-cpi-release/blob/3fc6d72d7c69b40416e78663238a15d022a98415/src/vsphere_cpi/lib/cloud/vsphere/resources/cluster.rb#L209-L216 [1] https://vdc-download.vmware.com/vmwb-repository/dcr-public/90ec343b-df7c-493e-9979-36ea55765102/8753fd1e-fcab-4bd4-9cde-a364851f31a6/vim.cluster.UsageSummary.html [2] https://vdc-download.vmware.com/vmwb-repository/dcr-public/3d076a12-29a2-4d17-9269-cb8150b5a37f/8b5969e2-1a66-4425-af17-feff6d6f705d/SDK/sms-sdk/docs/ReferenceGuide/vim.ComputeResource.Summary.html#effectiveMemory [#183481442]
1 parent a8e1a30 commit 600142d

2 files changed

Lines changed: 12 additions & 5 deletions

File tree

src/vsphere_cpi/lib/cloud/vsphere/resources/cluster.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def fetch_cluster_utilization()
212212
raise "Failed to get utilization for cluster'#{self.mob.name}'" if properties.nil?
213213

214214
compute_resource_summary = properties["summary"]
215-
return compute_resource_summary.effective_memory
215+
return compute_resource_summary.effective_memory - compute_resource_summary.usage_summary.mem_demand_mb
216216
end
217217

218218
# Fetches the resource pool utilization from vSphere.

src/vsphere_cpi/spec/unit/cloud/vsphere/resources/cluster_spec.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ def generate_host_property(mob:, name:, connection_state:, maintenance_mode:, me
171171
let(:active_host_1_mob) { instance_double('VimSdk::Vim::ClusterComputeResource') }
172172
let(:active_host_2_mob) { instance_double('VimSdk::Vim::ClusterComputeResource') }
173173
let(:active_host_mobs) { [active_host_1_mob, active_host_2_mob] }
174-
let(:compute_summary) { instance_double('VimSdk::Vim::ComputeResource::Summary') }
174+
let(:compute_summary) { instance_double('VimSdk::Vim::ClusterComputeResource::Summary') }
175+
let(:cluster_usage_summary) { instance_double('VimSdk::Vim::Cluster::UsageSummary') }
175176
let(:active_hosts_properties) do
176177
{}.merge(
177178
generate_host_property(mob: active_host_1_mob, name: 'mob-1', maintenance_mode: false, memory_size: 100 * 1024 * 1024, power_state: 'poweredOn', connection_state: 'connected')
@@ -183,7 +184,9 @@ def generate_host_property(mob:, name:, connection_state:, maintenance_mode:, me
183184

184185
before do
185186
allow(cloud_searcher).to receive(:get_properties).and_return({"summary" => compute_summary})
186-
allow(compute_summary).to receive(:effective_memory).and_return(85)
187+
allow(compute_summary).to receive(:effective_memory).and_return(90)
188+
allow(compute_summary).to receive(:usage_summary).and_return(cluster_usage_summary)
189+
allow(cluster_usage_summary).to receive(:mem_demand_mb).and_return(5)
187190
end
188191

189192
it 'sets resources to values based on the active hosts in the cluster' do
@@ -244,6 +247,7 @@ def generate_host_property(mob:, name:, connection_state:, maintenance_mode:, me
244247
end
245248
before do
246249
allow(compute_summary).to receive(:effective_memory).and_return(0)
250+
allow(cluster_usage_summary).to receive(:mem_demand_mb).and_return(0)
247251
end
248252
it 'defaults free memory to zero' do
249253
expect(cluster.free_memory.cluster_free_memory).to eq(0)
@@ -291,12 +295,15 @@ def generate_host_property(mob:, name:, connection_state:, maintenance_mode:, me
291295
end
292296

293297
context 'when host group rule type is SHOULD' do
294-
let(:compute_summary) { instance_double('VimSdk::Vim::ComputeResource::Summary') }
298+
let(:compute_summary) { instance_double('VimSdk::Vim::ClusterComputeResource::Summary') }
299+
let(:cluster_usage_summary) { instance_double('VimSdk::Vim::Cluster::UsageSummary') }
295300

296301
before do
297302
allow(subject).to receive(:host_group_rule_type).and_return('SHOULD')
298303
allow(cloud_searcher).to receive(:get_properties).and_return({"summary" => compute_summary})
299-
allow(compute_summary).to receive(:effective_memory).and_return(85)
304+
allow(compute_summary).to receive(:usage_summary).and_return(cluster_usage_summary)
305+
allow(compute_summary).to receive(:effective_memory).and_return(90)
306+
allow(cluster_usage_summary).to receive(:mem_demand_mb).and_return(5)
300307
end
301308

302309
it 'returns full cluster free memory in Megabytes for cluster free memory' do

0 commit comments

Comments
 (0)