Skip to content

Commit bd66d9a

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Ironic: report 0 for vcpus/memory_mb/disk_gb resources"
2 parents d61aa2f + a985e34 commit bd66d9a

File tree

4 files changed

+54
-167
lines changed

4 files changed

+54
-167
lines changed

nova/exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,3 +2364,7 @@ def __init__(self, message=None, **kwargs):
23642364
self.rc = results.get('rc')
23652365
self.rs = results.get('rs')
23662366
self.errmsg = results.get('errmsg')
2367+
2368+
2369+
class NoResourceClass(NovaException):
2370+
msg_fmt = _("Resource class not found for Ironic node %(node)s.")

nova/tests/unit/virt/ironic/test_driver.py

Lines changed: 24 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,12 @@ def test__node_resource_with_instance_uuid(self):
286286
gotkeys = sorted(result.keys())
287287
self.assertEqual(wantkeys, gotkeys)
288288

289-
self.assertEqual(props['cpus'], result['vcpus'])
290-
self.assertEqual(result['vcpus'], result['vcpus_used'])
291-
self.assertEqual(props['memory_mb'], result['memory_mb'])
292-
self.assertEqual(result['memory_mb'], result['memory_mb_used'])
293-
self.assertEqual(props['local_gb'], result['local_gb'])
294-
self.assertEqual(result['local_gb'], result['local_gb_used'])
289+
self.assertEqual(0, result['vcpus'])
290+
self.assertEqual(0, result['vcpus_used'])
291+
self.assertEqual(0, result['memory_mb'])
292+
self.assertEqual(0, result['memory_mb_used'])
293+
self.assertEqual(0, result['local_gb'])
294+
self.assertEqual(0, result['local_gb_used'])
295295
self.assertEqual(node_uuid, result['uuid'])
296296
self.assertEqual(node_uuid, result['hypervisor_hostname'])
297297
self.assertEqual(stats, result['stats'])
@@ -354,11 +354,11 @@ def test__node_resource_available(self):
354354
provision_state=ironic_states.AVAILABLE)
355355

356356
result = self.driver._node_resource(node)
357-
self.assertEqual(props['cpus'], result['vcpus'])
357+
self.assertEqual(0, result['vcpus'])
358358
self.assertEqual(0, result['vcpus_used'])
359-
self.assertEqual(props['memory_mb'], result['memory_mb'])
359+
self.assertEqual(0, result['memory_mb'])
360360
self.assertEqual(0, result['memory_mb_used'])
361-
self.assertEqual(props['local_gb'], result['local_gb'])
361+
self.assertEqual(0, result['local_gb'])
362362
self.assertEqual(0, result['local_gb_used'])
363363
self.assertEqual(node_uuid, result['hypervisor_hostname'])
364364
self.assertEqual(stats, result['stats'])
@@ -374,12 +374,12 @@ def test__node_resource_unavailable_node_res(self, mock_res_unavail):
374374
uuid=node_uuid, instance_uuid=None, properties=props)
375375

376376
result = self.driver._node_resource(node)
377-
self.assertEqual(props['cpus'], result['vcpus'])
378-
self.assertEqual(result['vcpus'], result['vcpus_used'])
379-
self.assertEqual(props['memory_mb'], result['memory_mb'])
380-
self.assertEqual(result['memory_mb'], result['memory_mb_used'])
381-
self.assertEqual(props['local_gb'], result['local_gb'])
382-
self.assertEqual(result['local_gb'], result['local_gb_used'])
377+
self.assertEqual(0, result['vcpus'])
378+
self.assertEqual(0, result['vcpus_used'])
379+
self.assertEqual(0, result['memory_mb'])
380+
self.assertEqual(0, result['memory_mb_used'])
381+
self.assertEqual(0, result['local_gb'])
382+
self.assertEqual(0, result['local_gb_used'])
383383
self.assertEqual(node_uuid, result['hypervisor_hostname'])
384384
self.assertEqual(stats, result['stats'])
385385

@@ -399,12 +399,12 @@ def test__node_resource_used_node_res(self, mock_res_used):
399399
instance_info=instance_info)
400400

401401
result = self.driver._node_resource(node)
402-
self.assertEqual(props['cpus'], result['vcpus'])
403-
self.assertEqual(result['vcpus'], result['vcpus_used'])
404-
self.assertEqual(props['memory_mb'], result['memory_mb'])
405-
self.assertEqual(result['memory_mb'], result['memory_mb_used'])
406-
self.assertEqual(props['local_gb'], result['local_gb'])
407-
self.assertEqual(result['local_gb'], result['local_gb_used'])
402+
self.assertEqual(0, result['vcpus'])
403+
self.assertEqual(0, result['vcpus_used'])
404+
self.assertEqual(0, result['memory_mb'])
405+
self.assertEqual(0, result['memory_mb_used'])
406+
self.assertEqual(0, result['local_gb'])
407+
self.assertEqual(0, result['local_gb_used'])
408408
self.assertEqual(node_uuid, result['hypervisor_hostname'])
409409
self.assertEqual(stats, result['stats'])
410410

@@ -733,40 +733,14 @@ def test_update_provider_tree_no_rc(self, mock_nfc, mock_nr,
733733
'resource_class': None,
734734
}
735735

736-
self.driver.update_provider_tree(self.ptree, mock.sentinel.nodename)
736+
self.assertRaises(exception.NoResourceClass,
737+
self.driver.update_provider_tree,
738+
self.ptree, mock.sentinel.nodename)
737739

738-
expected = {
739-
fields.ResourceClass.VCPU: {
740-
'total': 24,
741-
'reserved': 0,
742-
'min_unit': 1,
743-
'max_unit': 24,
744-
'step_size': 1,
745-
'allocation_ratio': 1.0,
746-
},
747-
fields.ResourceClass.MEMORY_MB: {
748-
'total': 1024,
749-
'reserved': 0,
750-
'min_unit': 1,
751-
'max_unit': 1024,
752-
'step_size': 1,
753-
'allocation_ratio': 1.0,
754-
},
755-
fields.ResourceClass.DISK_GB: {
756-
'total': 100,
757-
'reserved': 0,
758-
'min_unit': 1,
759-
'max_unit': 100,
760-
'step_size': 1,
761-
'allocation_ratio': 1.0,
762-
},
763-
}
764740
mock_nfc.assert_called_once_with(mock.sentinel.nodename)
765741
mock_nr.assert_called_once_with(mock_nfc.return_value)
766742
mock_res_used.assert_called_once_with(mock_nfc.return_value)
767743
mock_res_unavail.assert_called_once_with(mock_nfc.return_value)
768-
result = self.ptree.data(mock.sentinel.nodename).inventory
769-
self.assertEqual(expected, result)
770744

771745
@mock.patch.object(ironic_driver.IronicDriver,
772746
'_node_resources_used', return_value=False)
@@ -793,30 +767,6 @@ def test_update_provider_tree_with_rc(self, mock_nfc, mock_nr,
793767
self.driver.update_provider_tree(self.ptree, mock.sentinel.nodename)
794768

795769
expected = {
796-
fields.ResourceClass.VCPU: {
797-
'total': 24,
798-
'reserved': 0,
799-
'min_unit': 1,
800-
'max_unit': 24,
801-
'step_size': 1,
802-
'allocation_ratio': 1.0,
803-
},
804-
fields.ResourceClass.MEMORY_MB: {
805-
'total': 1024,
806-
'reserved': 0,
807-
'min_unit': 1,
808-
'max_unit': 1024,
809-
'step_size': 1,
810-
'allocation_ratio': 1.0,
811-
},
812-
fields.ResourceClass.DISK_GB: {
813-
'total': 100,
814-
'reserved': 0,
815-
'min_unit': 1,
816-
'max_unit': 100,
817-
'step_size': 1,
818-
'allocation_ratio': 1.0,
819-
},
820770
'CUSTOM_IRON_NFV': {
821771
'total': 1,
822772
'reserved': 0,
@@ -899,30 +849,6 @@ def test_update_provider_tree_with_rc_occupied(self, mock_nfc, mock_nr,
899849
self.driver.update_provider_tree(self.ptree, mock.sentinel.nodename)
900850

901851
expected = {
902-
fields.ResourceClass.VCPU: {
903-
'total': 24,
904-
'reserved': 0,
905-
'min_unit': 1,
906-
'max_unit': 24,
907-
'step_size': 1,
908-
'allocation_ratio': 1.0,
909-
},
910-
fields.ResourceClass.MEMORY_MB: {
911-
'total': 1024,
912-
'reserved': 0,
913-
'min_unit': 1,
914-
'max_unit': 1024,
915-
'step_size': 1,
916-
'allocation_ratio': 1.0,
917-
},
918-
fields.ResourceClass.DISK_GB: {
919-
'total': 100,
920-
'reserved': 0,
921-
'min_unit': 1,
922-
'max_unit': 100,
923-
'step_size': 1,
924-
'allocation_ratio': 1.0,
925-
},
926852
'CUSTOM_IRON_NFV': {
927853
'total': 1,
928854
'reserved': 0,
@@ -964,30 +890,6 @@ def test_update_provider_tree_disabled_node(self, mock_nfc, mock_nr,
964890
self.driver.update_provider_tree(self.ptree, mock.sentinel.nodename)
965891

966892
expected = {
967-
fields.ResourceClass.VCPU: {
968-
'total': 24,
969-
'reserved': 24,
970-
'min_unit': 1,
971-
'max_unit': 24,
972-
'step_size': 1,
973-
'allocation_ratio': 1.0,
974-
},
975-
fields.ResourceClass.MEMORY_MB: {
976-
'total': 1024,
977-
'reserved': 1024,
978-
'min_unit': 1,
979-
'max_unit': 1024,
980-
'step_size': 1,
981-
'allocation_ratio': 1.0,
982-
},
983-
fields.ResourceClass.DISK_GB: {
984-
'total': 100,
985-
'reserved': 100,
986-
'min_unit': 1,
987-
'max_unit': 100,
988-
'step_size': 1,
989-
'allocation_ratio': 1.0,
990-
},
991893
'CUSTOM_IRON_NFV': {
992894
'total': 1,
993895
'reserved': 1,

nova/virt/ironic/driver.py

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,6 @@ def _node_resource(self, node):
261261
"""Helper method to create resource dict from node stats."""
262262
properties = self._parse_node_properties(node)
263263

264-
vcpus = properties['cpus']
265-
memory_mb = properties['memory_mb']
266-
local_gb = properties['local_gb']
267264
raw_cpu_arch = properties['raw_cpu_arch']
268265
cpu_arch = properties['cpu_arch']
269266

@@ -296,17 +293,9 @@ def _node_resource(self, node):
296293
LOG.warning("Ignoring malformed capability '%s'. "
297294
"Format should be 'key:val'.", capability)
298295

299-
vcpus_used = 0
300-
memory_mb_used = 0
301-
local_gb_used = 0
302-
303-
if (self._node_resources_used(node)
304-
or self._node_resources_unavailable(node)):
305-
# Node is deployed, or is in a state when deployment can not start.
306-
# Report all of its resources as in use.
307-
vcpus_used = vcpus
308-
memory_mb_used = memory_mb
309-
local_gb_used = local_gb
296+
vcpus = vcpus_used = 0
297+
memory_mb = memory_mb_used = 0
298+
local_gb = local_gb_used = 0
310299

311300
dic = {
312301
'uuid': str(node.uuid),
@@ -788,10 +777,6 @@ def update_provider_tree(self, provider_tree, nodename):
788777
# nodename is the ironic node's UUID.
789778
node = self._node_from_cache(nodename)
790779
reserved = False
791-
# TODO(jaypipes): Completely remove the reporting of VCPU, MEMORY_MB,
792-
# and DISK_GB resource classes in early Queens when Ironic nodes will
793-
# *always* return the custom resource class that represents the
794-
# baremetal node class in an atomic, singular unit.
795780
if (not self._node_resources_used(node) and
796781
self._node_resources_unavailable(node)):
797782
LOG.debug('Node %(node)s is not ready for a deployment, '
@@ -804,35 +789,21 @@ def update_provider_tree(self, provider_tree, nodename):
804789

805790
info = self._node_resource(node)
806791
result = {}
807-
for rc, field in [(rc_fields.ResourceClass.VCPU, 'vcpus'),
808-
(rc_fields.ResourceClass.MEMORY_MB, 'memory_mb'),
809-
(rc_fields.ResourceClass.DISK_GB, 'local_gb')]:
810-
# NOTE(dtantsur): any of these fields can be zero starting with
811-
# the Pike release.
812-
if info[field]:
813-
result[rc] = {
814-
'total': info[field],
815-
'reserved': info[field] if reserved else 0,
816-
'min_unit': 1,
817-
'max_unit': info[field],
818-
'step_size': 1,
819-
'allocation_ratio': 1.0,
820-
}
821792

822793
rc_name = info.get('resource_class')
823-
if rc_name is not None:
824-
# TODO(jaypipes): Raise an exception in Queens if Ironic doesn't
825-
# report a resource class for the node
826-
norm_name = rc_fields.ResourceClass.normalize_name(rc_name)
827-
if norm_name is not None:
828-
result[norm_name] = {
829-
'total': 1,
830-
'reserved': int(reserved),
831-
'min_unit': 1,
832-
'max_unit': 1,
833-
'step_size': 1,
834-
'allocation_ratio': 1.0,
835-
}
794+
if rc_name is None:
795+
raise exception.NoResourceClass(node=nodename)
796+
797+
norm_name = rc_fields.ResourceClass.normalize_name(rc_name)
798+
if norm_name is not None:
799+
result[norm_name] = {
800+
'total': 1,
801+
'reserved': int(reserved),
802+
'min_unit': 1,
803+
'max_unit': 1,
804+
'step_size': 1,
805+
'allocation_ratio': 1.0,
806+
}
836807

837808
provider_tree.update_inventory(nodename, result)
838809
# TODO(efried): *Unset* (remove_traits) if "owned" by ironic virt but
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
upgrade:
3+
- |
4+
Ironic nodes are now only scheduled using the ``resource_class`` field set
5+
on the node. CPUs, RAM, and disks are not reported to the resource tracker.
6+
Ironic nodes must have the ``resource_class`` field set before upgrading.
7+
Flavors must also be configured to use resource classes instead of node
8+
properties. See the `ironic flavor configuration guide
9+
<https://docs.openstack.org/ironic/latest/install/configure-nova-flavors.html>`_
10+
for more information on doing this.

0 commit comments

Comments
 (0)