class BaseRedfishSystem(BaseSystem):
def __init__(self, **kw: Any) -> None:
super().__init__(**kw)
+ self.common_endpoints: List[str] = kw.get('common_endpoints', ['/Systems/System.Embedded.1',
+ '/UpdateService'])
+ self.chassis_endpoint: str = kw.get('chassis_endpoint', '/Chassis/System.Embedded.1')
self.log = Logger(__name__)
self.host: str = kw['host']
self.username: str = kw['username']
self.lock: Lock = Lock()
self.data: Dict[str, Dict[str, Any]] = {}
self._system: Dict[str, Dict[str, Any]] = {}
+ self._sys: Dict[str, Any] = {}
self.start_client()
def start_client(self) -> None:
self.log.logger.debug("lock acquired.")
try:
self._update_system()
- update_funcs = [self._update_metadata,
- self._update_memory,
+ self._update_sn()
+ update_funcs = [self._update_memory,
self._update_power,
self._update_fans,
self._update_network,
self._update_processors,
- self._update_storage]
+ self._update_storage,
+ self._update_firmwares]
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.map(lambda f: f(), update_funcs)
raise RuntimeError(f"Could not get path: {path}")
return result
- def get_members(self, path: str) -> List:
- _path = self._system[path]['@odata.id']
- data = self._get_path(_path)
- return [self._get_path(member['@odata.id']) for member in data['Members']]
-
- def build_data(self,
- fields: List,
- path: str) -> Dict[str, Dict[str, Dict]]:
- raise NotImplementedError()
-
- # def _update_system(self) -> None:
- # raise NotImplementedError()
+ def get_members(self, data: Dict[str, Any], path: str) -> List:
+ _path = data[path]['@odata.id']
+ _data = self._get_path(_path)
+ return [self._get_path(member['@odata.id']) for member in _data['Members']]
def get_system(self) -> Dict[str, Dict[str, Dict]]:
result = {
'memory': self.get_memory(),
'power': self.get_power(),
'fans': self.get_fans()
- }
+ },
+ 'firmwares': self.get_firmwares()
}
return result
def _update_system(self) -> None:
- redfish_system = self.client.get_path(self.system_endpoint)
- self._system = {**redfish_system, **self._system}
+ for endpoint in self.common_endpoints:
+ result = self.client.get_path(endpoint)
+ _endpoint = endpoint.strip('/').split('/')[0]
+ self._system[_endpoint] = result
- def _update_metadata(self) -> None:
+ def _update_sn(self) -> None:
raise NotImplementedError()
def _update_memory(self) -> None:
def _update_storage(self) -> None:
raise NotImplementedError()
+
+ def _update_firmwares(self) -> None:
+ raise NotImplementedError()
def get_storage(self) -> Dict[str, Dict[str, Dict]]:
raise NotImplementedError()
+ def get_firmwares(self) -> Dict[str, Dict[str, Dict]]:
+ raise NotImplementedError()
+
def get_sn(self) -> str:
raise NotImplementedError()
import cherrypy
from threading import Thread
-from .redfish_dell import RedfishDell
+from .redfishdellsystem import RedfishDellSystem
from .reporter import Reporter
from .util import Config, Logger
from typing import Dict, Any, Optional
def main(self) -> None:
# TODO: add a check and fail if host/username/password/data aren't passed
-
config = Config('/etc/ceph/node-proxy.yml', default_config=DEFAULT_CONFIG)
-
log = Logger(__name__, level=config.__dict__['logging']['level'])
# create the redfish system and the obsever
log.logger.info(f"Server initialization...")
try:
- self.system = RedfishDell(host=self.__dict__['host'],
- username=self.__dict__['username'],
- password=self.__dict__['password'],
- system_endpoint='/Systems/System.Embedded.1',
- config=config)
+ self.system = RedfishDellSystem(host=self.__dict__['host'],
+ username=self.__dict__['username'],
+ password=self.__dict__['password'],
+ config=config)
except RuntimeError:
log.logger.error("Can't initialize the redfish system.")
raise
+++ /dev/null
-from .redfishdellchassis import RedfishDellChassis
-from .redfishdellsystem import RedfishDellSystem
-from .util import Logger
-from typing import Any
-
-
-class RedfishDell(RedfishDellSystem, RedfishDellChassis):
- def __init__(self, **kw: Any) -> None:
- if kw.get('system_endpoint') is None:
- kw['system_endpoint'] = '/Systems/System.Embedded.1'
- if kw.get('chassis_endpoint') is None:
- kw['chassis_endpoint'] = '/Chassis/System.Embedded.1'
- super().__init__(**kw)
- self.log = Logger(__name__)
+++ /dev/null
-from .baseredfishsystem import BaseRedfishSystem
-from .redfish_client import RedFishClient
-from threading import Thread, Lock
-from time import sleep
-from .util import Logger, retry, normalize_dict, to_snake_case
-from typing import Dict, Any, List, Union
-
-
-class RedfishDellChassis(BaseRedfishSystem):
- def __init__(self, **kw: Any) -> None:
- self.chassis_endpoint = kw.get('chassis_endpoint', '/Chassis/System.Embedded.1')
- super().__init__(**kw)
- self.log = Logger(__name__)
- self.log.logger.info(f"{__name__} initialization.")
-
- def get_power(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['power']
-
- def get_fans(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['fans']
-
- def get_chassis(self) -> Dict[str, Dict[str, Dict]]:
- result = {
- 'power': self.get_power(),
- 'fans': self.get_fans()
- }
- return result
-
- def _update_power(self) -> None:
- fields = {
- "PowerSupplies": [
- "Name",
- "Model",
- "Manufacturer",
- "Status"
- ]
- }
- self.log.logger.debug("Updating powersupplies")
- self._system['power'] = self.build_chassis_data(fields, 'Power')
-
- def _update_fans(self) -> None:
- fields = {
- "Fans": [
- "Name",
- "PhysicalContext",
- "Status"
- ],
- }
- self.log.logger.debug("Updating fans")
- self._system['fans'] = self.build_chassis_data(fields, 'Thermal')
-
- def build_chassis_data(self,
- fields: Dict[str, List[str]],
- path: str) -> Dict[str, Dict[str, Dict]]:
- result: Dict[str, Dict[str, Dict]] = dict()
- data = self._get_path(f"{self.chassis_endpoint}/{path}")
-
- for elt, _fields in fields.items():
- for member_elt in data[elt]:
- _id = member_elt['MemberId']
- result[_id] = dict()
- for field in _fields:
- try:
- result[_id][to_snake_case(field)] = member_elt[field]
- except KeyError:
- self.log.logger.warning(f"Could not find field: {field} in data: {data[elt]}")
- return normalize_dict(result)
class RedfishDellSystem(BaseRedfishSystem):
def __init__(self, **kw: Any) -> None:
- self.system_endpoint = kw.get('systemd_endpoint', '/Systems/System.Embedded.1')
super().__init__(**kw)
self.log = Logger(__name__)
- def build_system_data(self,
- fields: List,
- path: str) -> Dict[str, Dict[str, Dict]]:
+ def build_common_data(self,
+ data: Dict[str, Any],
+ fields: List,
+ path: str) -> Dict[str, Dict[str, Dict]]:
result: Dict[str, Dict[str, Dict]] = dict()
- for member_info in self.get_members(path):
+ for member_info in self.get_members(data, path):
member_id = member_info['Id']
result[member_id] = dict()
for field in fields:
return normalize_dict(result)
+ def build_chassis_data(self,
+ fields: Dict[str, List[str]],
+ path: str) -> Dict[str, Dict[str, Dict]]:
+ result: Dict[str, Dict[str, Dict]] = dict()
+ data = self._get_path(f"{self.chassis_endpoint}/{path}")
+
+ for elt, _fields in fields.items():
+ for member_elt in data[elt]:
+ _id = member_elt['MemberId']
+ result[_id] = dict()
+ for field in _fields:
+ try:
+ result[_id][to_snake_case(field)] = member_elt[field]
+ except KeyError:
+ self.log.logger.warning(f"Could not find field: {field} in data: {data[elt]}")
+ return normalize_dict(result)
+
+
def get_sn(self) -> str:
- return self._system['SKU']
+ return self._sys['SKU']
def get_status(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['status']
-
- def get_metadata(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['metadata']
+ return self._sys['status']
def get_memory(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['memory']
+ return self._sys['memory']
def get_processors(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['processors']
+ return self._sys['processors']
def get_network(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['network']
+ return self._sys['network']
def get_storage(self) -> Dict[str, Dict[str, Dict]]:
- return self._system['storage']
+ return self._sys['storage']
+
+ def get_firmwares(self) -> Dict[str, Dict[str, Dict]]:
+ return self._sys['firmwares']
+
+ def get_power(self) -> Dict[str, Dict[str, Dict]]:
+ return self._sys['power']
- # def _update_system(self) -> None:
- # redfish_system = self.client.get_path(self.system_endpoint)
- # self._system = {**redfish_system, **self._system}
+ def get_fans(self) -> Dict[str, Dict[str, Dict]]:
+ return self._sys['fans']
def _update_network(self) -> None:
fields = ['Description', 'Name', 'SpeedMbps', 'Status']
self.log.logger.debug('Updating network')
- self._system['network'] = self.build_system_data(fields, 'EthernetInterfaces')
+ self._sys['network'] = self.build_common_data(data=self._system['Systems'],
+ fields=fields,
+ path='EthernetInterfaces')
def _update_processors(self) -> None:
fields = ['Description',
'Status',
'Manufacturer']
self.log.logger.debug('Updating processors')
- self._system['processors'] = self.build_system_data(fields, 'Processors')
+ self._sys['processors'] = self.build_common_data(data=self._system['Systems'],
+ fields=fields,
+ path='Processors')
def _update_storage(self) -> None:
fields = ['Description',
'Model', 'Protocol',
'SerialNumber', 'Status',
'PhysicalLocation']
- entities = self.get_members('Storage')
+ entities = self.get_members(data=self._system['Systems'],
+ path='Storage')
self.log.logger.debug('Updating storage')
result: Dict[str, Dict[str, Dict]] = dict()
for entity in entities:
for field in fields:
result[drive_id][to_snake_case(field)] = drive_info[field]
result[drive_id]['entity'] = entity['Id']
- self._system['storage'] = normalize_dict(result)
+ self._sys['storage'] = normalize_dict(result)
- def _update_metadata(self) -> None:
- self.log.logger.debug('Updating metadata')
- pass
+ def _update_sn(self) -> None:
+ self.log.logger.debug('Updating serial number')
+ self._sys['SKU'] = self._system['Systems']['SKU']
def _update_memory(self) -> None:
fields = ['Description',
'CapacityMiB',
'Status']
self.log.logger.debug('Updating memory')
- self._system['memory'] = self.build_system_data(fields, 'Memory')
+ self._sys['memory'] = self.build_common_data(data=self._system['Systems'],
+ fields=fields,
+ path='Memory')
+
+ def _update_power(self) -> None:
+ fields = {
+ 'PowerSupplies': [
+ 'Name',
+ 'Model',
+ 'Manufacturer',
+ 'Status'
+ ]
+ }
+ self.log.logger.debug('Updating powersupplies')
+ self._sys['power'] = self.build_chassis_data(fields, 'Power')
+
+ def _update_fans(self) -> None:
+ fields = {
+ 'Fans': [
+ 'Name',
+ 'PhysicalContext',
+ 'Status'
+ ],
+ }
+ self.log.logger.debug('Updating fans')
+ self._sys['fans'] = self.build_chassis_data(fields, 'Thermal')
+
+ def _update_firmwares(self) -> None:
+ fields = [
+ 'Name',
+ 'Description',
+ 'ReleaseDate',
+ 'Version',
+ 'Updateable',
+ 'Status',
+ ]
+ self.log.logger.debug('Updating firmwares')
+ self._sys['firmwares'] = self.build_common_data(data=self._system['UpdateService'],
+ fields=fields,
+ path='FirmwareInventory')
+ self.log.logger.warning(f"guits-debug1:{self._sys['firmwares']}")
def common(self, **kw) -> Dict[str, Any]:
return self.mgr.node_proxy.common(**kw)
+ @cherrypy.expose
+ @cherrypy.tools.allow(methods=['GET'])
+ @cherrypy.tools.json_out()
+ def firmwares(self, **kw) -> Dict[str, Any]:
+ return self.mgr.node_proxy.firmwares(**kw)
+
def dispatch(self, hostname='', cmd=''):
kw = dict(hostname=hostname, cmd=cmd)
try:
else:
return _result
+ def firmwares(self, **kw: Any) -> Dict[str, Any]:
+ """
+ Retrieves firmware information for a specific hostname or all hosts.
+
+ If a 'hostname' is provided in the keyword arguments, retrieves firmware
+ information for that specific host. Otherwise, retrieves firmware
+ information for all available hosts.
+
+ :param kw: Keyword arguments, including 'hostname' if specified.
+ :type kw: dict
+
+ :return: A dictionary containing firmware information for each host.
+ :rtype: Dict[str, Any]
+ """
+ hostname = kw.get('hostname')
+ hosts = [hostname] if hostname else self.data.keys()
+
+ return {host: self.data[host]['firmwares'] for host in hosts}
+
def criticals(self, **kw):
return {}