Fix cells capacity calculation for n:1 virt drivers

The capacity calculation in cells assumes a 1:1 mapping for
compute_hosts:nova-compute. Fix this calculation to allow for
drivers that have an n:1 mapping.

Co-Authored-By: John Villalovos <john.l.villalovos@intel.com>
Closes-Bug: 1385468
Change-Id: If361b8bedd81147120581f7f9fe43b8b3f4325e5
This commit is contained in:
Jim Rollenhagen 2014-10-24 12:40:27 -07:00 committed by John L. Villalovos
parent 498fab3111
commit d50f4fef26
2 changed files with 64 additions and 16 deletions

View File

@ -16,6 +16,7 @@
"""
CellState Manager
"""
import collections
import copy
import datetime
import functools
@ -259,7 +260,10 @@ class CellStateManager(base.Base):
ctxt = context.get_admin_context()
reserve_level = CONF.cells.reserve_percent / 100.0
compute_hosts = {}
def _defaultdict_int():
return collections.defaultdict(int)
compute_hosts = collections.defaultdict(_defaultdict_int)
def _get_compute_hosts():
service_refs = {service.host: service
@ -273,11 +277,13 @@ class CellStateManager(base.Base):
if not service or service['disabled']:
continue
compute_hosts[host] = {
'free_ram_mb': compute['free_ram_mb'],
'free_disk_mb': compute['free_disk_gb'] * 1024,
'total_ram_mb': compute['memory_mb'],
'total_disk_mb': compute['local_gb'] * 1024}
chost = compute_hosts[host]
chost['free_ram_mb'] += compute['free_ram_mb']
free_disk = compute['free_disk_gb'] * 1024
chost['free_disk_mb'] += free_disk
chost['total_ram_mb'] += compute['memory_mb']
total_disk = compute['local_gb'] * 1024
chost['total_disk_mb'] += total_disk
_get_compute_hosts()
if not compute_hosts:

View File

@ -38,6 +38,13 @@ FAKE_COMPUTES = [
('host4', 1024, 100, 300, 30),
]
FAKE_COMPUTES_N_TO_ONE = [
('host1', 1024, 100, 0, 0),
('host1', 1024, 100, -1, -1),
('host2', 1024, 100, 1024, 100),
('host2', 1024, 100, 300, 30),
]
# NOTE(alaski): It's important to have multiple types that end up having the
# same memory and disk requirements. So two types need the same first value,
# and two need the second and third values to add up to the same thing.
@ -49,16 +56,12 @@ FAKE_ITYPES = [
]
@classmethod
def _fake_compute_node_get_all(cls, context):
def _node(host, total_mem, total_disk, free_mem, free_disk):
return objects.ComputeNode(host=host,
memory_mb=total_mem,
local_gb=total_disk,
free_ram_mb=free_mem,
free_disk_gb=free_disk)
return [_node(*fake) for fake in FAKE_COMPUTES]
def _create_fake_node(host, total_mem, total_disk, free_mem, free_disk):
return objects.ComputeNode(host=host,
memory_mb=total_mem,
local_gb=total_disk,
free_ram_mb=free_mem,
free_disk_gb=free_disk)
@classmethod
@ -69,6 +72,16 @@ def _fake_service_get_all_by_binary(cls, context, binary):
return [_node(*fake) for fake in FAKE_COMPUTES]
@classmethod
def _fake_compute_node_get_all(cls, context):
return [_create_fake_node(*fake) for fake in FAKE_COMPUTES]
@classmethod
def _fake_compute_node_n_to_one_get_all(cls, context):
return [_create_fake_node(*fake) for fake in FAKE_COMPUTES_N_TO_ONE]
def _fake_cell_get_all(context):
return []
@ -187,6 +200,35 @@ class TestCellsStateManager(test.NoDBTestCase):
return my_state.capacities
class TestCellsStateManagerNToOne(TestCellsStateManager):
def setUp(self):
super(TestCellsStateManagerNToOne, self).setUp()
self.stubs.Set(objects.ComputeNodeList, 'get_all',
_fake_compute_node_n_to_one_get_all)
def test_capacity_part_reserve(self):
# utilize half the cell's free capacity
cap = self._capacity(50.0)
cell_free_ram = sum(compute[3] for compute in FAKE_COMPUTES_N_TO_ONE)
self.assertEqual(cell_free_ram, cap['ram_free']['total_mb'])
cell_free_disk = (1024 *
sum(compute[4] for compute in FAKE_COMPUTES_N_TO_ONE))
self.assertEqual(cell_free_disk, cap['disk_free']['total_mb'])
self.assertEqual(0, cap['ram_free']['units_by_mb']['0'])
self.assertEqual(0, cap['disk_free']['units_by_mb']['0'])
units = 6 # 6 from host 2
self.assertEqual(units, cap['ram_free']['units_by_mb']['50'])
sz = 25 * 1024
units = 1 # 1 on host 2
self.assertEqual(units, cap['disk_free']['units_by_mb'][str(sz)])
class TestCellStateManagerException(test.NoDBTestCase):
@mock.patch.object(time, 'sleep')
def test_init_db_error(self, mock_sleep):