summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-03-11 17:34:11 +0000
committerGerrit Code Review <review@openstack.org>2013-03-11 17:34:11 +0000
commit79ea0ab67a864c9a4edaa7b89e6eec3d27266879 (patch)
tree9f6b491cb7883b3a55e5437a8b95a09065a1d0eb
parentfb18fb32c05a8fc082653423331af1cd78db2b43 (diff)
parent0b488849cce3bfd4dc4b5b9ad001a17c29376823 (diff)
Merge "Add ability to control max utilization of a cell"
-rw-r--r--nova/cells/opts.py4
-rw-r--r--nova/cells/state.py20
-rw-r--r--nova/tests/cells/test_cells_state_manager.py128
3 files changed, 145 insertions, 7 deletions
diff --git a/nova/cells/opts.py b/nova/cells/opts.py
index b66dd6b42..203f98687 100644
--- a/nova/cells/opts.py
+++ b/nova/cells/opts.py
@@ -39,6 +39,10 @@ cells_opts = [
cfg.IntOpt('call_timeout',
default=60,
help='Seconds to wait for response from a call to a cell.'),
+ cfg.FloatOpt('reserve_percent',
+ default=10.0,
+ help='Percentage of cell capacity to hold in reserve. '
+ 'Affects both memory and disk utilization'),
]
cfg.CONF.register_opts(cells_opts, group='cells')
diff --git a/nova/cells/state.py b/nova/cells/state.py
index 53c536888..d7646c528 100644
--- a/nova/cells/state.py
+++ b/nova/cells/state.py
@@ -40,6 +40,7 @@ LOG = logging.getLogger(__name__)
CONF = cfg.CONF
CONF.import_opt('name', 'nova.cells.opts', group='cells')
+CONF.import_opt('reserve_percent', 'nova.cells.opts', group='cells')
#CONF.import_opt('capabilities', 'nova.cells.opts', group='cells')
CONF.register_opts(cell_state_manager_opts, group='cells')
@@ -196,6 +197,7 @@ class CellStateManager(base.Base):
available per instance_type.
"""
+ reserve_level = CONF.cells.reserve_percent / 100.0
compute_hosts = {}
def _get_compute_hosts():
@@ -207,7 +209,9 @@ class CellStateManager(base.Base):
host = service['host']
compute_hosts[host] = {
'free_ram_mb': compute['free_ram_mb'],
- 'free_disk_mb': compute['free_disk_gb'] * 1024}
+ 'free_disk_mb': compute['free_disk_gb'] * 1024,
+ 'total_ram_mb': compute['memory_mb'],
+ 'total_disk_mb': compute['local_gb'] * 1024}
_get_compute_hosts()
if not compute_hosts:
@@ -219,9 +223,11 @@ class CellStateManager(base.Base):
total_ram_mb_free = 0
total_disk_mb_free = 0
- def _free_units(tot, per_inst):
+ def _free_units(total, free, per_inst):
if per_inst:
- return max(0, int(tot / per_inst))
+ min_free = total * reserve_level
+ free = max(0, free - min_free)
+ return int(free / per_inst)
else:
return 0
@@ -231,10 +237,10 @@ class CellStateManager(base.Base):
instance_type['ephemeral_gb']) * 1024
ram_mb_free_units.setdefault(str(memory_mb), 0)
disk_mb_free_units.setdefault(str(disk_mb), 0)
- ram_free_units = _free_units(compute_values['free_ram_mb'],
- memory_mb)
- disk_free_units = _free_units(compute_values['free_disk_mb'],
- disk_mb)
+ ram_free_units = _free_units(compute_values['total_ram_mb'],
+ compute_values['free_ram_mb'], memory_mb)
+ disk_free_units = _free_units(compute_values['total_disk_mb'],
+ compute_values['free_disk_mb'], disk_mb)
ram_mb_free_units[str(memory_mb)] += ram_free_units
disk_mb_free_units[str(disk_mb)] += disk_free_units
diff --git a/nova/tests/cells/test_cells_state_manager.py b/nova/tests/cells/test_cells_state_manager.py
new file mode 100644
index 000000000..078578926
--- /dev/null
+++ b/nova/tests/cells/test_cells_state_manager.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2013 Rackspace Hosting
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""
+Tests For CellsStateManager
+"""
+
+from nova.cells import state
+from nova import db
+from nova import test
+
+
+FAKE_COMPUTES = [
+ ('host1', 1024, 100, 0, 0),
+ ('host2', 1024, 100, -1, -1),
+ ('host3', 1024, 100, 1024, 100),
+ ('host4', 1024, 100, 300, 30),
+]
+
+FAKE_ITYPES = [
+ (0, 0, 0),
+ (50, 12, 13),
+]
+
+
+def _fake_compute_node_get_all(context):
+ def _node(host, total_mem, total_disk, free_mem, free_disk):
+ service = {'host': host, 'disabled': False}
+ return {'service': service,
+ '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 _fake_instance_type_all(context):
+ def _type(mem, root, eph):
+ return {'root_gb': root,
+ 'ephemeral_gb': eph,
+ 'memory_mb': mem}
+
+ return [_type(*fake) for fake in FAKE_ITYPES]
+
+
+class TestCellsStateManager(test.TestCase):
+
+ def setUp(self):
+ super(TestCellsStateManager, self).setUp()
+
+ self.stubs.Set(db, 'compute_node_get_all', _fake_compute_node_get_all)
+ self.stubs.Set(db, 'instance_type_get_all', _fake_instance_type_all)
+
+ def test_capacity_no_reserve(self):
+ # utilize entire cell
+ cap = self._capacity(0.0)
+
+ cell_free_ram = sum(compute[3] for compute in FAKE_COMPUTES)
+ self.assertEqual(cell_free_ram, cap['ram_free']['total_mb'])
+
+ cell_free_disk = 1024 * sum(compute[4] for compute in FAKE_COMPUTES)
+ 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 = cell_free_ram / 50
+ self.assertEqual(units, cap['ram_free']['units_by_mb']['50'])
+
+ sz = 25 * 1024
+ units = 5 # 4 on host 3, 1 on host4
+ self.assertEqual(units, cap['disk_free']['units_by_mb'][str(sz)])
+
+ def test_capacity_full_reserve(self):
+ # reserve the entire cell. (utilize zero percent)
+ cap = self._capacity(100.0)
+
+ cell_free_ram = sum(compute[3] for compute in FAKE_COMPUTES)
+ self.assertEqual(cell_free_ram, cap['ram_free']['total_mb'])
+
+ cell_free_disk = 1024 * sum(compute[4] for compute in FAKE_COMPUTES)
+ 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'])
+ self.assertEqual(0, cap['ram_free']['units_by_mb']['50'])
+
+ sz = 25 * 1024
+ self.assertEqual(0, cap['disk_free']['units_by_mb'][str(sz)])
+
+ 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)
+ self.assertEqual(cell_free_ram, cap['ram_free']['total_mb'])
+
+ cell_free_disk = 1024 * sum(compute[4] for compute in FAKE_COMPUTES)
+ 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 = 10 # 10 from host 3
+ self.assertEqual(units, cap['ram_free']['units_by_mb']['50'])
+
+ sz = 25 * 1024
+ units = 2 # 2 on host 3
+ self.assertEqual(units, cap['disk_free']['units_by_mb'][str(sz)])
+
+ def _capacity(self, reserve_percent):
+ self.flags(reserve_percent=reserve_percent, group='cells')
+
+ mgr = state.CellStateManager()
+ my_state = mgr.get_my_state()
+ return my_state.capacities