diff options
Diffstat (limited to 'ironic')
23 files changed, 169 insertions, 144 deletions
diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index bbd2355bd..ef850753d 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -2284,10 +2284,13 @@ class ConductorManager(base_manager.BaseConductorManager): LOG.debug("RPC create_port called for port %s.", port_uuid) with task_manager.acquire(context, port_obj.node_id, - purpose='port create') as task: + purpose='port create', + shared=True) as task: + # NOTE(TheJulia): We're creating a port, we don't need + # an exclusive parent lock to do so. utils.validate_port_physnet(task, port_obj) port_obj.create() - return port_obj + return port_obj @METRICS.timer('ConductorManager.update_port') @messaging.expected_exceptions(exception.NodeLocked, @@ -2373,7 +2376,7 @@ class ConductorManager(base_manager.BaseConductorManager): port_obj.save() - return port_obj + return port_obj @METRICS.timer('ConductorManager.update_portgroup') @messaging.expected_exceptions(exception.NodeLocked, @@ -2452,7 +2455,7 @@ class ConductorManager(base_manager.BaseConductorManager): portgroup_obj.save() - return portgroup_obj + return portgroup_obj @METRICS.timer('ConductorManager.update_volume_connector') @messaging.expected_exceptions( @@ -2496,7 +2499,7 @@ class ConductorManager(base_manager.BaseConductorManager): connector.save() LOG.info("Successfully updated volume connector %(connector)s.", {'connector': connector.uuid}) - return connector + return connector @METRICS.timer('ConductorManager.update_volume_target') @messaging.expected_exceptions( @@ -2537,7 +2540,7 @@ class ConductorManager(base_manager.BaseConductorManager): target.save() LOG.info("Successfully updated volume target %(target)s.", {'target': target.uuid}) - return target + return target @METRICS.timer('ConductorManager.get_driver_properties') @messaging.expected_exceptions(exception.DriverNotFound) @@ -3564,7 +3567,7 @@ class ConductorManager(base_manager.BaseConductorManager): {'node': task.node.uuid}) utils.add_secret_token(task.node) task.node.save() - return task.node + return objects.Node.get(context, node_id) @METRICS.timer('ConductorManager.manage_node_history') @periodics.periodic( diff --git a/ironic/conductor/utils.py b/ironic/conductor/utils.py index 2272c0df7..39886bfd8 100644 --- a/ironic/conductor/utils.py +++ b/ironic/conductor/utils.py @@ -499,6 +499,11 @@ def cleaning_error_handler(task, logmsg, errmsg=None, traceback=False, # NOTE(dtantsur): avoid overwriting existing maintenance_reason if not node.maintenance_reason and set_maintenance: node.maintenance_reason = errmsg + + if CONF.conductor.poweroff_in_cleanfail: + # NOTE(NobodyCam): Power off node in clean fail + node_power_action(task, states.POWER_OFF) + node.save() if set_fail_state and node.provision_state != states.CLEANFAIL: @@ -803,7 +808,6 @@ def power_state_error_handler(e, node, power_state): {'node': node.uuid, 'power_state': power_state}) -@task_manager.require_exclusive_lock def validate_port_physnet(task, port_obj): """Validate the consistency of physical networks of ports in a portgroup. diff --git a/ironic/conf/conductor.py b/ironic/conf/conductor.py index 653e30f56..2452fafe7 100644 --- a/ironic/conf/conductor.py +++ b/ironic/conf/conductor.py @@ -349,6 +349,14 @@ opts = [ 'is a global setting applying to all requests this ' 'conductor receives, regardless of access rights. ' 'The concurrent clean limit cannot be disabled.')), + + cfg.BoolOpt('poweroff_in_cleanfail', + default=False, + help=_('If True power off nodes in the ``clean failed`` ' + 'state. Default False. Option may be unsafe ' + 'when using Cleaning to perform ' + 'hardware-transformative actions such as ' + 'firmware upgrade.')), ] diff --git a/ironic/conf/opts.py b/ironic/conf/opts.py index a7ebcfb30..0d8aeafd2 100644 --- a/ironic/conf/opts.py +++ b/ironic/conf/opts.py @@ -78,7 +78,6 @@ def update_opt_defaults(): # This comes in two flavors 'oslo.messaging=INFO', 'oslo_messaging=INFO', - 'sqlalchemy=WARNING', 'stevedore=INFO', 'eventlet.wsgi.server=INFO', 'iso8601=WARNING', diff --git a/ironic/db/sqlalchemy/__init__.py b/ironic/db/sqlalchemy/__init__.py index 173b91fcc..c656ed227 100644 --- a/ironic/db/sqlalchemy/__init__.py +++ b/ironic/db/sqlalchemy/__init__.py @@ -10,9 +10,28 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_config import cfg from oslo_db.sqlalchemy import enginefacade +from sqlalchemy.engine import Engine +from sqlalchemy import event + +CONF = cfg.CONF # FIXME(stephenfin): we need to remove reliance on autocommit semantics ASAP # since it's not compatible with SQLAlchemy 2.0 # NOTE(dtantsur): we want sqlite as close to a real database as possible. enginefacade.configure(sqlite_fk=True, __autocommit=True) + + +# NOTE(TheJulia): Setup a listener to trigger the sqlite write-ahead +# log to be utilized to permit concurrent access, which is needed +# as we can get read requests while we are writing via the API +# surface *when* we're using sqlite as the database backend. +@event.listens_for(Engine, "connect") +def _setup_journal_mode(dbapi_connection, connection_record): + # NOTE(TheJulia): The string may not be loaded in some unit + # tests so handle whatever the output is as a string so we + # can lower/compare it and send the appropriate command to + # the database. + if 'sqlite' in str(CONF.database.connection).lower(): + dbapi_connection.execute("PRAGMA journal_mode=WAL") diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py index 93a211fc3..3ba31e233 100644 --- a/ironic/db/sqlalchemy/api.py +++ b/ironic/db/sqlalchemy/api.py @@ -324,7 +324,9 @@ def _paginate_query(model, limit=None, marker=None, sort_key=None, # object is garbage collected as ORM Query objects allow # for DB interactions to occur after the fact, so it remains # connected to the DB.. - return query.all() + # Save the query.all() results, but don't return yet, so we + # begin to exit and unwind the session. + ref = query.all() else: # In this case, we have a sqlalchemy.sql.selectable.Select # (most likely) which utilizes the unified select interface. @@ -338,7 +340,10 @@ def _paginate_query(model, limit=None, marker=None, sort_key=None, # Everything is a tuple in a resultset from the unified interface # but for objects, our model expects just object access, # so we extract and return them. - return [r[0] for r in res] + ref = [r[0] for r in res] + # Return the results to the caller, outside of the session context + # if an ORM object, because we want the session to close. + return ref def _filter_active_conductors(query, interval=None): @@ -1341,6 +1346,12 @@ class Connection(api.Connection): def get_active_hardware_type_dict(self, use_groups=False): with _session_for_read() as session: + # TODO(TheJulia): We should likely take a look at this + # joined query, as we may not be getting what we expect. + # Metal3 logs upwards of 200 rows returned with multiple datetime + # columns. + # Given dualing datetime fields, we really can't just expect + # requesting a unique set to "just work". query = (session.query(models.ConductorHardwareInterfaces, models.Conductor) .join(models.Conductor)) @@ -1375,16 +1386,19 @@ class Connection(api.Connection): with _session_for_read() as session: query = (session.query(models.ConductorHardwareInterfaces) .filter_by(conductor_id=conductor_id)) - return query.all() + ref = query.all() + return ref def list_hardware_type_interfaces(self, hardware_types): with _session_for_read() as session: - query = (session.query(models.ConductorHardwareInterfaces) + query = (session.query(models.ConductorHardwareInterfaces, + models.Conductor) + .join(models.Conductor) .filter(models.ConductorHardwareInterfaces.hardware_type .in_(hardware_types))) query = _filter_active_conductors(query) - return query.all() + return [row[0] for row in query] @oslo_db_api.retry_on_deadlock def register_conductor_hardware_interfaces(self, conductor_id, interfaces): @@ -1395,6 +1409,8 @@ class Connection(api.Connection): conductor_hw_iface['conductor_id'] = conductor_id for k, v in iface.items(): conductor_hw_iface[k] = v + # TODO(TheJulia): Uhh... We should try to do this as one + # bulk operation and not insert each row. session.add(conductor_hw_iface) session.flush() except db_exc.DBDuplicateEntry as e: @@ -2078,9 +2094,10 @@ class Connection(api.Connection): query = session.query(models.Allocation).filter_by( id=allocation_id) try: - return query.one() + ref = query.one() except NoResultFound: raise exception.AllocationNotFound(allocation=allocation_id) + return ref def get_allocation_by_uuid(self, allocation_uuid): """Return an allocation representation. @@ -2093,9 +2110,10 @@ class Connection(api.Connection): query = session.query(models.Allocation).filter_by( uuid=allocation_uuid) try: - return query.one() + ref = query.one() except NoResultFound: raise exception.AllocationNotFound(allocation=allocation_uuid) + return ref def get_allocation_by_name(self, name): """Return an allocation representation. @@ -2107,9 +2125,10 @@ class Connection(api.Connection): with _session_for_read() as session: query = session.query(models.Allocation).filter_by(name=name) try: - return query.one() + ref = query.one() except NoResultFound: raise exception.AllocationNotFound(allocation=name) + return ref def get_allocation_list(self, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None): @@ -2453,7 +2472,7 @@ class Connection(api.Connection): session.flush() except db_exc.DBDuplicateEntry: raise exception.NodeHistoryAlreadyExists(uuid=values['uuid']) - return history + return history @oslo_db_api.retry_on_deadlock def destroy_node_history_by_uuid(self, history_uuid): @@ -2467,9 +2486,10 @@ class Connection(api.Connection): def get_node_history_by_id(self, history_id): query = model_query(models.NodeHistory).filter_by(id=history_id) try: - return query.one() + res = query.one() except NoResultFound: raise exception.NodeHistoryNotFound(history=history_id) + return res def get_node_history_by_uuid(self, history_uuid): query = model_query(models.NodeHistory).filter_by(uuid=history_uuid) diff --git a/ironic/drivers/base.py b/ironic/drivers/base.py index bdd017b91..953ac056e 100644 --- a/ironic/drivers/base.py +++ b/ironic/drivers/base.py @@ -1224,7 +1224,7 @@ class InspectInterface(BaseInterface): """Interface for inspection-related actions.""" interface_type = 'inspect' - ESSENTIAL_PROPERTIES = {'memory_mb', 'local_gb', 'cpus', 'cpu_arch'} + ESSENTIAL_PROPERTIES = {'memory_mb', 'local_gb', 'cpu_arch'} """The properties required by scheduler/deploy.""" @abc.abstractmethod @@ -1662,7 +1662,7 @@ class NetworkInterface(BaseInterface): """ def need_power_on(self, task): - """Check if ironic node must be powered on before applying network changes + """Check if node must be powered on before applying network changes :param task: A TaskManager instance. :returns: Boolean. diff --git a/ironic/drivers/modules/drac/inspect.py b/ironic/drivers/modules/drac/inspect.py index 8ba0be088..c9c58fbe9 100644 --- a/ironic/drivers/modules/drac/inspect.py +++ b/ironic/drivers/modules/drac/inspect.py @@ -176,8 +176,6 @@ class DracWSManInspect(base.InspectInterface): [memory.size_mb for memory in client.list_memory()]) cpus = client.list_cpus() if cpus: - properties['cpus'] = sum( - [self._calculate_cpus(cpu) for cpu in cpus]) properties['cpu_arch'] = 'x86_64' if cpus[0].arch64 else 'x86' bios_settings = client.list_bios_settings() @@ -264,18 +262,6 @@ class DracWSManInspect(base.InspectInterface): if disk.size_mb >= min_size_required_mb: return disk - def _calculate_cpus(self, cpu): - """Find actual CPU count. - - :param cpu: Pass cpu. - - :returns: returns total cpu count. - """ - if cpu.ht_enabled: - return cpu.cores * 2 - else: - return cpu.cores - def _calculate_gpus(self, video_controllers): """Find actual GPU count. diff --git a/ironic/drivers/modules/drac/raid.py b/ironic/drivers/modules/drac/raid.py index 8bad02bba..404222f5d 100644 --- a/ironic/drivers/modules/drac/raid.py +++ b/ironic/drivers/modules/drac/raid.py @@ -1022,7 +1022,7 @@ def _commit_to_controllers(node, controllers, substep="completed"): # all realtime controllers all_realtime = all( (cntlr['is_reboot_required'] == optional) - and not(cntlr.get('is_ehba_mode')) + and not (cntlr.get('is_ehba_mode')) for cntlr in controllers) # check any controller with ehba mode diff --git a/ironic/drivers/modules/irmc/inspect.py b/ironic/drivers/modules/irmc/inspect.py index f7c2ad7ba..64708ff9b 100644 --- a/ironic/drivers/modules/irmc/inspect.py +++ b/ironic/drivers/modules/irmc/inspect.py @@ -236,7 +236,7 @@ def _inspect_hardware(node, existing_traits=None, **kwargs): "with the server, please check if you have set them " "correctly.") error = (_("Inspection failed for node %(node_id)s " - "with the following error: %(error)s. (advice)s") % + "with the following error: %(error)s. %(advice)s") % {'node_id': node.uuid, 'error': e, 'advice': advice}) raise exception.HardwareInspectionFailure(error=error) diff --git a/ironic/drivers/modules/redfish/inspect.py b/ironic/drivers/modules/redfish/inspect.py index 4c5f7c344..c514df4fe 100644 --- a/ironic/drivers/modules/redfish/inspect.py +++ b/ironic/drivers/modules/redfish/inspect.py @@ -108,9 +108,7 @@ class RedfishInspect(base.InspectInterface): system.memory_summary.size_gib * units.Ki) if system.processors and system.processors.summary: - cpus, arch = system.processors.summary - if cpus: - inspected_properties['cpus'] = cpus + arch = system.processors.summary[1] if arch: try: diff --git a/ironic/hacking/checks.py b/ironic/hacking/checks.py index 6c5b49776..57a3cbfe8 100644 --- a/ironic/hacking/checks.py +++ b/ironic/hacking/checks.py @@ -51,4 +51,4 @@ def check_explicit_underscore_import(logical_line, filename): UNDERSCORE_IMPORT_FILES.append(filename) elif (translated_log.match(logical_line) or string_translation.match(logical_line)): - yield(0, "N323: Found use of _() without explicit import of _!") + yield (0, "N323: Found use of _() without explicit import of _!") diff --git a/ironic/objects/node.py b/ironic/objects/node.py index 93df5b3c1..b680ac60a 100644 --- a/ironic/objects/node.py +++ b/ironic/objects/node.py @@ -29,7 +29,7 @@ from ironic.objects import base from ironic.objects import fields as object_fields from ironic.objects import notification -REQUIRED_INT_PROPERTIES = ['local_gb', 'cpus', 'memory_mb'] +REQUIRED_INT_PROPERTIES = ['local_gb', 'memory_mb'] CONF = cfg.CONF LOG = log.getLogger(__name__) @@ -191,7 +191,7 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat): return d def _validate_property_values(self, properties): - """Check if the input of local_gb, cpus and memory_mb are valid. + """Check if the input of local_gb and memory_mb are valid. :param properties: a dict contains the node's information. """ diff --git a/ironic/tests/base.py b/ironic/tests/base.py index 348f15c20..69e449d3b 100644 --- a/ironic/tests/base.py +++ b/ironic/tests/base.py @@ -102,6 +102,11 @@ class WarningsFixture(fixtures.Fixture): category=UserWarning, ) + # NOTE(gibi): The UUIDFields emits a warning if the value is not a + # valid UUID. Let's escalate that to an exception in the test to + # prevent adding violations. + warnings.filterwarnings('error', message='.* is an invalid UUID.') + # Enable deprecation warnings to capture upcoming SQLAlchemy changes warnings.filterwarnings( @@ -125,16 +130,6 @@ class WarningsFixture(fixtures.Fixture): category=sqla_exc.SAWarning, ) - # ...but filter everything out until we get around to fixing them - # TODO(stephenfin): Fix all of these - - warnings.filterwarnings( - 'ignore', - module='ironic', - message='SELECT statement has a cartesian product ', - category=sqla_exc.SAWarning, - ) - # FIXME(stephenfin): We can remove this once oslo.db is fixed # https://review.opendev.org/c/openstack/oslo.db/+/856453 warnings.filterwarnings( diff --git a/ironic/tests/unit/conductor/test_cleaning.py b/ironic/tests/unit/conductor/test_cleaning.py index 34e805deb..cdfbf14ee 100644 --- a/ironic/tests/unit/conductor/test_cleaning.py +++ b/ironic/tests/unit/conductor/test_cleaning.py @@ -436,6 +436,36 @@ class DoNodeCleanTestCase(db_base.DbTestCase): self.assertFalse(node.maintenance) self.assertIsNone(node.fault) + @mock.patch('ironic.drivers.modules.fake.FakePower.set_power_state', + autospec=True) + @mock.patch.object(n_flat.FlatNetwork, 'validate', autospec=True) + @mock.patch.object(conductor_steps, 'set_node_cleaning_steps', + autospec=True) + def test_do_node_clean_steps_fail_poweroff(self, mock_steps, mock_validate, + mock_power, clean_steps=None, + invalid_exc=True): + if invalid_exc: + mock_steps.side_effect = exception.InvalidParameterValue('invalid') + else: + mock_steps.side_effect = exception.NodeCleaningFailure('failure') + tgt_prov_state = states.MANAGEABLE if clean_steps else states.AVAILABLE + self.config(poweroff_in_cleanfail=True, group='conductor') + node = obj_utils.create_test_node( + self.context, driver='fake-hardware', + uuid=uuidutils.generate_uuid(), + provision_state=states.CLEANING, + power_state=states.POWER_ON, + target_provision_state=tgt_prov_state) + with task_manager.acquire( + self.context, node.uuid, shared=False) as task: + cleaning.do_node_clean(task, clean_steps=clean_steps) + mock_validate.assert_called_once_with(mock.ANY, task) + node.refresh() + self.assertEqual(states.CLEANFAIL, node.provision_state) + self.assertEqual(tgt_prov_state, node.target_provision_state) + mock_steps.assert_called_once_with(mock.ANY, disable_ramdisk=False) + self.assertTrue(mock_power.called) + def test__do_node_clean_automated_steps_fail(self): for invalid in (True, False): self.__do_node_clean_steps_fail(invalid_exc=invalid) diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py index 7278486a5..f0fb075b7 100644 --- a/ironic/tests/unit/conductor/test_manager.py +++ b/ironic/tests/unit/conductor/test_manager.py @@ -3568,6 +3568,23 @@ class MiscTestCase(mgr_utils.ServiceSetUpMixin, mgr_utils.CommonMixIn, filters=mock.sentinel.filters)) self.assertEqual([], result) + def test_get_node_with_token(self): + node = obj_utils.create_test_node( + self.context, driver='fake-hardware', + network_interface='noop') + self.assertNotIn('agent_secret_token', node.driver_internal_info) + res = self.service.get_node_with_token(self.context, node.id) + self.assertIn('agent_secret_token', res.driver_internal_info) + + def test_node_with_token_already_set(self): + node = obj_utils.create_test_node( + self.context, driver='fake-hardware', + network_interface='noop', + driver_internal_info={'agent_secret_token': 'secret'}) + res = self.service.get_node_with_token(self.context, node.id) + self.assertEqual('******', + res.driver_internal_info['agent_secret_token']) + @mgr_utils.mock_record_keepalive class ConsoleTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): @@ -3953,18 +3970,6 @@ class CreatePortTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): self.assertEqual({'foo': 'bar'}, res.extra) mock_validate.assert_called_once_with(mock.ANY, port) - def test_create_port_node_locked(self): - node = obj_utils.create_test_node(self.context, driver='fake-hardware', - reservation='fake-reserv') - port = obj_utils.get_test_port(self.context, node_id=node.id) - exc = self.assertRaises(messaging.rpc.ExpectedException, - self.service.create_port, - self.context, port) - # Compare true exception hidden by @messaging.expected_exceptions - self.assertEqual(exception.NodeLocked, exc.exc_info[0]) - self.assertRaises(exception.PortNotFound, port.get_by_uuid, - self.context, port.uuid) - @mock.patch.object(conductor_utils, 'validate_port_physnet', autospec=True) def test_create_port_mac_exists(self, mock_validate): node = obj_utils.create_test_node(self.context, driver='fake-hardware') @@ -5089,7 +5094,8 @@ class ManagerDoSyncPowerStateTestCase(db_base.DbTestCase): self.power = self.driver.power self.node = obj_utils.create_test_node( self.context, driver='fake-hardware', maintenance=False, - provision_state=states.AVAILABLE, instance_uuid=uuidutils.uuid) + provision_state=states.AVAILABLE, + instance_uuid=uuidutils.generate_uuid()) self.task = mock.Mock(spec_set=['context', 'driver', 'node', 'upgrade_lock', 'shared']) self.task.context = self.context diff --git a/ironic/tests/unit/conductor/test_utils.py b/ironic/tests/unit/conductor/test_utils.py index 52fc72436..27c4bfa86 100644 --- a/ironic/tests/unit/conductor/test_utils.py +++ b/ironic/tests/unit/conductor/test_utils.py @@ -243,11 +243,12 @@ class NodePowerActionTestCase(db_base.DbTestCase): self.config(host='my-host') # Required for exception handling mock_notif.__name__ = 'NodeSetPowerStateNotification' - node = obj_utils.create_test_node(self.context, - uuid=uuidutils.generate_uuid(), - driver='fake-hardware', - instance_uuid=uuidutils.uuid, - power_state=states.POWER_OFF) + node = obj_utils.create_test_node( + self.context, + uuid=uuidutils.generate_uuid(), + driver='fake-hardware', + instance_uuid=uuidutils.generate_uuid(), + power_state=states.POWER_OFF) task = task_manager.TaskManager(self.context, node.uuid) get_power_mock.return_value = states.POWER_OFF diff --git a/ironic/tests/unit/db/utils.py b/ironic/tests/unit/db/utils.py index 10055d829..fc5bee226 100644 --- a/ironic/tests/unit/db/utils.py +++ b/ironic/tests/unit/db/utils.py @@ -165,7 +165,6 @@ def get_test_snmp_info(**kw): def get_test_node(**kw): properties = { "cpu_arch": "x86_64", - "cpus": "8", "local_gb": "10", "memory_mb": "4096", } @@ -509,7 +508,6 @@ def create_test_node_tag(**kw): def get_test_xclarity_properties(): return { "cpu_arch": "x86_64", - "cpus": "8", "local_gb": "10", "memory_mb": "4096", } diff --git a/ironic/tests/unit/drivers/modules/drac/test_inspect.py b/ironic/tests/unit/drivers/modules/drac/test_inspect.py index d12adba34..0c04ad887 100644 --- a/ironic/tests/unit/drivers/modules/drac/test_inspect.py +++ b/ironic/tests/unit/drivers/modules/drac/test_inspect.py @@ -185,7 +185,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): expected_node_properties = { 'memory_mb': 32768, 'local_gb': 1116, - 'cpus': 18, 'cpu_arch': 'x86_64', 'capabilities': 'boot_mode:uefi,pci_gpu_devices:1'} mock_client = mock.Mock() @@ -235,7 +234,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): expected_node_properties = { 'memory_mb': 32768, 'local_gb': 279, - 'cpus': 18, 'cpu_arch': 'x86_64', 'capabilities': 'boot_mode:uefi,pci_gpu_devices:1'} mock_client = mock.Mock() @@ -305,7 +303,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): expected_node_properties = { 'memory_mb': 32768, 'local_gb': 279, - 'cpus': 18, 'cpu_arch': 'x86_64', 'capabilities': 'boot_mode:uefi,pci_gpu_devices:0'} mock_client = mock.Mock() @@ -355,7 +352,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): expected_node_properties = { 'memory_mb': 32768, 'local_gb': 279, - 'cpus': 18, 'cpu_arch': 'x86_64', 'capabilities': 'boot_mode:uefi,pci_gpu_devices:2'} mock_client = mock.Mock() @@ -387,7 +383,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): expected_node_properties = { 'memory_mb': 32768, 'local_gb': 279, - 'cpus': 18, 'cpu_arch': 'x86_64', 'capabilities': 'boot_mode:uefi,pci_gpu_devices:0'} mock_client = mock.Mock() @@ -417,7 +412,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): expected_node_properties = { 'memory_mb': 32768, 'local_gb': 1116, - 'cpus': 18, 'cpu_arch': 'x86_64', 'capabilities': 'boot_mode:uefi,pci_gpu_devices:1'} mock_client = mock.Mock() @@ -449,22 +443,6 @@ class DracInspectionTestCase(test_utils.BaseDracTest): self.assertEqual(285888, root_disk.size_mb) - def test__calculate_cpus(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - cpu = task.driver.inspect._calculate_cpus( - self.cpus[0]) - - self.assertEqual(12, cpu) - - def test__calculate_cpus_without_ht_enabled(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - cpu = task.driver.inspect._calculate_cpus( - self.cpus[1]) - - self.assertEqual(6, cpu) - @mock.patch.object(drac_common, 'get_drac_client', spec_set=True, autospec=True) def test__get_pxe_dev_nics_with_UEFI_boot_mode(self, mock_get_drac_client): diff --git a/ironic/tests/unit/drivers/modules/ilo/test_inspect.py b/ironic/tests/unit/drivers/modules/ilo/test_inspect.py index 1a85d5b28..af262c0d0 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_inspect.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_inspect.py @@ -65,7 +65,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {} result = {'properties': properties, 'macs': macs} @@ -103,8 +103,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_capabilities_mock, log_mock): ilo_object_mock = get_ilo_object_mock.return_value - properties = {'memory_mb': '512', 'local_gb': 0, - 'cpus': '1', 'cpu_arch': 'x86_64'} + properties = {'memory_mb': '512', 'local_gb': 0, 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {} result = {'properties': properties, 'macs': macs} @@ -118,7 +117,7 @@ class IloInspectTestCase(test_common.BaseIloTest): task.node.properties = properties task.node.save() expected_properties = {'memory_mb': '512', 'local_gb': 10, - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) @@ -149,8 +148,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_capabilities_mock, log_mock): ilo_object_mock = get_ilo_object_mock.return_value - properties = {'memory_mb': '512', 'local_gb': 10, - 'cpus': '1', 'cpu_arch': 'x86_64'} + properties = {'memory_mb': '512', 'local_gb': 10, 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {'server_model': 'Gen8'} result = {'properties': properties, 'macs': macs} @@ -160,7 +158,7 @@ class IloInspectTestCase(test_common.BaseIloTest): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: expected_properties = {'memory_mb': '512', 'local_gb': 10, - 'cpus': '1', 'cpu_arch': 'x86_64', + 'cpu_arch': 'x86_64', 'capabilities': 'server_model:Gen8'} task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) @@ -195,8 +193,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_security_params_mock, log_mock): ilo_object_mock = get_ilo_object_mock.return_value - properties = {'memory_mb': '512', 'local_gb': 10, - 'cpus': '1', 'cpu_arch': 'x86_64'} + properties = {'memory_mb': '512', 'local_gb': 10, 'cpu_arch': 'x86_64'} macs = {'NIC.LOM.1.1': 'aa:aa:aa:aa:aa:aa'} capabilities = {'server_model': 'Gen10'} security_params = ( @@ -209,7 +206,7 @@ class IloInspectTestCase(test_common.BaseIloTest): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: expected_properties = { - 'memory_mb': '512', 'local_gb': 10, 'cpus': '1', + 'memory_mb': '512', 'local_gb': 10, 'cpu_arch': 'x86_64', 'capabilities': 'server_model:Gen10', 'security_parameters': {'Password Complexity': 'ok'}} task.driver.inspect.inspect_hardware(task) @@ -243,7 +240,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {} result = {'properties': properties, 'macs': macs} @@ -280,7 +277,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capability_str = 'sriov_enabled:true' capabilities = {'sriov_enabled': 'true'} @@ -292,7 +289,7 @@ class IloInspectTestCase(test_common.BaseIloTest): shared=False) as task: task.driver.inspect.inspect_hardware(task) expected_properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64', + 'cpu_arch': 'x86_64', 'capabilities': capability_str} self.assertEqual(expected_properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) @@ -320,8 +317,7 @@ class IloInspectTestCase(test_common.BaseIloTest): get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64', - 'somekey': 'somevalue'} + 'cpu_arch': 'x86_64', 'somekey': 'somevalue'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} result = {'properties': properties, 'macs': macs} capabilities = {'sriov_enabled': 'true'} @@ -339,7 +335,7 @@ class IloInspectTestCase(test_common.BaseIloTest): set2 = set(end_capabilities.split(',')) self.assertEqual(set1, set2) expected_properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64', + 'cpu_arch': 'x86_64', 'capabilities': end_capabilities} power_mock.assert_called_once_with(mock.ANY, task) self.assertEqual(task.node.properties, expected_properties) @@ -356,7 +352,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): def test__get_essential_properties_ok(self): ilo_mock = mock.MagicMock(spec=['get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result @@ -368,8 +364,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): ilo_mock = mock.MagicMock( spec=['get_additional_capabilities', 'get_essential_properties']) # Missing key: cpu_arch - properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1'} + properties = {'memory_mb': '512', 'local_gb': '10'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result @@ -386,8 +381,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): ilo_mock = mock.MagicMock( spec=['get_additional_capabilities', 'get_essential_properties']) # Not a dict - properties = ['memory_mb', '512', 'local_gb', '10', - 'cpus', '1'] + properties = ['memory_mb', '512', 'local_gb', '10'] macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb'] capabilities = '' result = {'properties': properties, 'macs': macs} @@ -400,7 +394,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): def test__get_essential_properties_fail_mac_invalid_format(self): ilo_mock = mock.MagicMock(spec=['get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} # Not a dict macs = 'aa:aa:aa:aa:aa:aa' result = {'properties': properties, 'macs': macs} @@ -413,7 +407,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): ilo_mock = mock.MagicMock( spec=['get_additional_capabilities', 'get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} # Not a dictionary macs = None result = {'properties': properties, 'macs': macs} @@ -427,7 +421,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): def test__get_essential_properties_hardware_port_not_dict(self): ilo_mock = mock.MagicMock(spec=['get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1', 'cpu_arch': 'x86_64'} + 'cpu_arch': 'x86_64'} # Not a dict macs = 'aa:bb:cc:dd:ee:ff' result = {'properties': properties, 'macs': macs} @@ -447,7 +441,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): def test__validate_ok(self): properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '2', 'cpu_arch': 'x86_arch'} + 'cpu_arch': 'x86_arch'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa'} data = {'properties': properties, 'macs': macs} valid_keys = ilo_inspect.IloInspect.ESSENTIAL_PROPERTIES @@ -455,8 +449,7 @@ class TestInspectPrivateMethods(test_common.BaseIloTest): self.assertEqual(sorted(set(properties)), sorted(valid_keys)) def test__validate_essential_keys_fail_missing_key(self): - properties = {'memory_mb': '512', 'local_gb': '10', - 'cpus': '1'} + properties = {'memory_mb': '512', 'local_gb': '10'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa'} data = {'properties': properties, 'macs': macs} self.assertRaises(exception.HardwareInspectionFailure, diff --git a/ironic/tests/unit/drivers/modules/irmc/test_inspect.py b/ironic/tests/unit/drivers/modules/irmc/test_inspect.py index 2cec2429f..e8762391f 100644 --- a/ironic/tests/unit/drivers/modules/irmc/test_inspect.py +++ b/ironic/tests/unit/drivers/modules/irmc/test_inspect.py @@ -83,7 +83,6 @@ class IRMCInspectInternalMethodsTestCase(test_common.BaseIRMCTest): inspected_props = { 'memory_mb': '1024', 'local_gb': 10, - 'cpus': 2, 'cpu_arch': 'x86_64'} inspected_capabilities = { 'irmc_firmware_version': 'iRMC S4-7.82F', @@ -142,7 +141,6 @@ class IRMCInspectInternalMethodsTestCase(test_common.BaseIRMCTest): inspected_props = { 'memory_mb': '1024', 'local_gb': 10, - 'cpus': 2, 'cpu_arch': 'x86_64'} inspected_capabilities = { 'irmc_firmware_version': 'iRMC S6-2.00S', @@ -260,7 +258,6 @@ class IRMCInspectTestCase(test_common.BaseIRMCTest): inspected_props = { 'memory_mb': '1024', 'local_gb': 10, - 'cpus': 2, 'cpu_arch': 'x86_64'} inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb'] new_traits = ['CUSTOM_CPU_FPGA'] @@ -318,7 +315,6 @@ class IRMCInspectTestCase(test_common.BaseIRMCTest): inspected_props = { 'memory_mb': '1024', 'local_gb': 10, - 'cpus': 2, 'cpu_arch': 'x86_64'} inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb'] new_traits = ['CUSTOM_CPU_FPGA'] @@ -398,7 +394,6 @@ class IRMCInspectTestCase(test_common.BaseIRMCTest): inspected_props = { 'memory_mb': '1024', 'local_gb': 10, - 'cpus': 2, 'cpu_arch': 'x86_64'} inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb'] existing_traits = ['CUSTOM_CPU_FPGA'] @@ -459,7 +454,6 @@ class IRMCInspectTestCase(test_common.BaseIRMCTest): inspected_props = { 'memory_mb': '1024', 'local_gb': 10, - 'cpus': 2, 'cpu_arch': 'x86_64'} inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb'] diff --git a/ironic/tests/unit/drivers/modules/redfish/test_inspect.py b/ironic/tests/unit/drivers/modules/redfish/test_inspect.py index dc1ffff4d..995dbb6d9 100644 --- a/ironic/tests/unit/drivers/modules/redfish/test_inspect.py +++ b/ironic/tests/unit/drivers/modules/redfish/test_inspect.py @@ -93,8 +93,7 @@ class RedfishInspectTestCase(db_base.DbTestCase): mock_get_system): expected_properties = { 'capabilities': 'boot_mode:uefi', - 'cpu_arch': 'mips', 'cpus': '8', - 'local_gb': '3', 'memory_mb': '2048' + 'cpu_arch': 'mips', 'local_gb': '3', 'memory_mb': '2048' } self.init_system_mock(mock_get_system.return_value) @@ -140,8 +139,7 @@ class RedfishInspectTestCase(db_base.DbTestCase): shared=True) as task: expected_properties = { 'capabilities': 'boot_mode:uefi', - 'cpu_arch': 'x86_64', 'cpus': '8', - 'local_gb': '3', 'memory_mb': '2048' + 'cpu_arch': 'x86_64', 'local_gb': '3', 'memory_mb': '2048' } task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) @@ -156,8 +154,7 @@ class RedfishInspectTestCase(db_base.DbTestCase): shared=True) as task: expected_properties = { 'capabilities': 'boot_mode:uefi', - 'cpu_arch': 'mips', 'cpus': '8', - 'local_gb': '0', 'memory_mb': '2048' + 'cpu_arch': 'mips', 'local_gb': '0', 'memory_mb': '2048' } task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) @@ -182,8 +179,7 @@ class RedfishInspectTestCase(db_base.DbTestCase): shared=True) as task: expected_properties = { 'capabilities': 'boot_mode:uefi', - 'cpu_arch': 'mips', 'cpus': '8', - 'local_gb': '3', 'memory_mb': '4096' + 'cpu_arch': 'mips', 'local_gb': '3', 'memory_mb': '4096' } task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) @@ -212,8 +208,7 @@ class RedfishInspectTestCase(db_base.DbTestCase): } expected_properties = { 'capabilities': 'boot_mode:bios', - 'cpu_arch': 'mips', 'cpus': '8', - 'local_gb': '3', 'memory_mb': '2048' + 'cpu_arch': 'mips', 'local_gb': '3', 'memory_mb': '2048' } task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) @@ -226,8 +221,7 @@ class RedfishInspectTestCase(db_base.DbTestCase): with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: expected_properties = { - 'cpu_arch': 'mips', 'cpus': '8', - 'local_gb': '3', 'memory_mb': '2048' + 'cpu_arch': 'mips', 'local_gb': '3', 'memory_mb': '2048' } task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) diff --git a/ironic/tests/unit/objects/test_node.py b/ironic/tests/unit/objects/test_node.py index 146120644..5ba823a89 100644 --- a/ironic/tests/unit/objects/test_node.py +++ b/ironic/tests/unit/objects/test_node.py @@ -534,10 +534,10 @@ class TestNodeObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn): autospec=True) as mock_get_node: mock_get_node.return_value = self.fake_node node = objects.Node.get(self.context, uuid) - node.properties = {"local_gb": "5G", "memory_mb": "5", - 'cpus': '-1', 'cpu_arch': 'x86_64'} + node.properties = {"local_gb": "5G", "memory_mb": "-5", + 'cpu_arch': 'x86_64'} self.assertRaisesRegex(exception.InvalidParameterValue, - ".*local_gb=5G, cpus=-1$", node.save) + ".*local_gb=5G, memory_mb=-5$", node.save) mock_get_node.assert_called_once_with(uuid) def test__validate_property_values_success(self): @@ -549,7 +549,6 @@ class TestNodeObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn): values = self.fake_node expect = { 'cpu_arch': 'x86_64', - "cpus": '8', "local_gb": '10', "memory_mb": '4096', } |