Files
sushy-tools/sushy_tools/emulator/resources/managers.py
Queensly Acheampongmaa 81352b1d34 Add PATCH support for Redfish DateTime fields in Manager resource
This patch enables PATCH support for the DateTime and DateTimeLocalOffset
fields of the Redfish Manager resource in sushy-tools, allowing clients like
sushy to update the BMC clock through the Redfish interface.

Key changes:
- In managers.py, added set_datetime() and get_datetime() methods in the
  FakeDriver class. These store and retrieve datetime values as instance
  attributes (not indexed by UUID), since each instance represents a single
  manager.
- In main.py, added PATCH support in the Manager resource handler.
  Removed reset_cache() hook to preserve instance state across
  requests, enabling PATCH updates to persist.
- In test_main.py, mocked get_datetime() return values to support unit
  tests for the datetime PATCH logic.
- In test_managers.py, added a unit test for the set_datetime() and
  get_datetime() methods.

Also includes a release note describing the new functionality.

Change-Id: I91c671316d8c646fa6cd80c926a2c8b872a7a1fa
2025-06-11 15:04:26 +00:00

119 lines
3.9 KiB
Python

# 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.
from sushy_tools.emulator.resources import base
from sushy_tools import error
class FakeDriver(base.DriverBase):
"""Redfish manager that copied systems."""
def __init__(self, config, logger, systems, chassis):
super().__init__(config, logger)
self._systems = systems
self._chassis = chassis
self._datetime = None
self._datetimelocaloffset = None
def get_manager(self, identity):
"""Get a manager by its identity
:returns: Redfish manager UUID.
:raises: NotFound if the manager cannot be found
"""
try:
system_uuid = self._systems.uuid(identity)
system_name = self._systems.name(identity)
except error.AliasAccessError:
raise
except error.NotFound:
# Re-raise hiding the fact that managers are backed by systems
msg = 'Manager with UUID %s was not found' % identity
self._logger.error(msg)
raise error.NotFound(msg)
else:
result = {'Id': system_uuid,
'UUID': system_uuid,
'Name': '%s-Manager' % system_name}
self._logger.debug(
'Found manager %(mgr)s by UUID %(id)s',
{'mgr': result, 'id': identity}
)
return result
def set_datetime(self, datetime_value, datetimelocaloffset_value):
"""Set the datetime and offset information for a manager
:param datetime_value: The datetime string to set
:param datetimelocaloffset_value:
The time zone offset to set (e.g., "+00:00")
"""
self._datetime = datetime_value
self._datetimelocaloffset = datetimelocaloffset_value
def get_datetime(self):
"""Retrieve the datetime and offset information for a manager
:returns: A dictionary with 'DateTime' and 'DateTimeLocalOffset' keys,
or an empty dict if no values are set
"""
if self._datetime and self._datetimelocaloffset:
return {
'DateTime': self._datetime,
'DateTimeLocalOffset': self._datetimelocaloffset
}
return {}
@property
def driver(self):
"""Return human-friendly driver information
:returns: driver information as `str`
"""
return '<static-managers>'
@property
def managers(self):
"""Return available Redfish managers
:returns: list of UUIDs representing the managers
"""
return sorted(self._systems.systems)
def get_managed_systems(self, manager):
"""Get systems managed by this manager.
:param manager: Redfish manager object.
:returns: List of Redfish system UUIDs.
"""
return [manager['UUID']]
def get_managed_chassis(self, manager):
"""Get chassis managed by this manager.
:param manager: Redfish manager object.
:returns: List of Redfish chassis UUIDs.
"""
if manager['UUID'] == self.managers[0]:
return self._chassis.chassis
else:
return []
def get_managers_for_system(self, ident):
"""Get managers that manage the given system.
:param ident: System UUID.
:returns: list of UUIDs representing the managers
"""
return [self._systems.uuid(ident)]