--- /dev/null
+
+system_1 = {
+
+ 'metadata': {
+ 'name': 'xx',
+ 'manufacturer': 'Dell',
+ 'model': 'HP PowerEdge',
+ 'chassis': 'xxx',
+ 'xxx': '',
+ },
+
+ 'status': {
+ 'State': 'Enabled',
+ 'Health': 'OK'
+ },
+
+ 'processor': {
+ 'description': '',
+ 'count': '',
+ 'type': '',
+ 'model': '',
+ 'temperature': '',
+ 'status': {
+ 'State': 'Enabled',
+ 'Health': 'OK'
+ }
+ },
+
+ 'memory': {
+ 'description': '',
+ 'total': 'xx',
+ 'status': {
+ 'State': 'Enabled',
+ 'Health': 'OK'
+ },
+ },
+
+ 'network': {
+ 'interfaces': [
+ {
+ 'type': 'ethernet',
+ 'description': 'my ethertnet interface',
+ 'name': 'name of the interface',
+ 'description': 'description of the interface',
+ 'speed_mbps': 'xxx',
+ 'status': {
+ 'State': 'Enabled',
+ 'Health': 'OK'
+ },
+ }
+ ]
+ },
+
+ 'storage': {
+ 'drives': [
+ {
+ 'device': 'devc',
+ 'description': 'Milk, Cheese, Bread, Fruit, Vegetables',
+ 'model': 'Buy groceries',
+ 'type': 'ssd|rotate|nvme',
+ 'capacity_bytes': '',
+ 'usage_bytes': '',
+ 'status': {
+ 'State': 'Enabled',
+ 'Health': 'OK'
+ },
+ }
+ ]
+ },
+
+ 'power': {
+ 'power_supplies': [
+ 'type': 'xx',
+ 'manufacturer': 'xxx',
+ 'model': 'xx',
+ 'properties': {},
+ 'power_control': 'xx',
+ 'status': {
+ 'State': 'Enabled',
+ 'Health': 'OK'
+ }
+ ]
+ },
+
+ 'cooling': {
+ 'fans': [
+ {
+ 'id': 1,
+ 'status': '',
+ }
+ ]
+ },
+}
--- /dev/null
+#!/usr/bin/env python3
+"""
+License: MIT License
+Copyright (c) 2023 Miel Donkers
+
+Very simple HTTP server in python for logging requests
+Usage::
+ ./server.py [<port>]
+"""
+from http.server import BaseHTTPRequestHandler, HTTPServer
+import logging
+
+class S(BaseHTTPRequestHandler):
+ def _set_response(self):
+ self.send_response(200)
+ self.send_header('Content-type', 'text/html')
+ self.end_headers()
+
+ def do_GET(self):
+ logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers))
+ self._set_response()
+ self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))
+
+ def do_POST(self):
+ content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
+ post_data = self.rfile.read(content_length) # <--- Gets the data itself
+ logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n",
+ str(self.path), str(self.headers), post_data.decode('utf-8'))
+
+ self._set_response()
+ self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))
+
+def run(server_class=HTTPServer, handler_class=S, port=8000):
+ logging.basicConfig(level=logging.INFO)
+ server_address = ('', port)
+ httpd = server_class(server_address, handler_class)
+ logging.info(f'Starting httpd on port {port}...\n')
+ try:
+ httpd.serve_forever()
+ except KeyboardInterrupt:
+ pass
+ httpd.server_close()
+ logging.info('Stopping httpd...\n')
+
+if __name__ == '__main__':
+ from sys import argv
+
+ if len(argv) == 2:
+ run(port=int(argv[1]))
+ else:
+ run()
--- /dev/null
+from redfish_system import RedfishSystem
+import time
+
+host = "https://x.x.x.x:8443"
+username = "myuser"
+password = "mypassword"
+
+system = RedfishSystem(host, username, password)
+system.start_update_loop()
+time.sleep(20)
+print(system.get_status())
+system.stop_update_loop()
--- /dev/null
+from redfish.rest.v1 import ServerDownOrUnreachableError
+import redfish
+import sys
+
+
+login_host = "https://x.x.x.x:8443"
+login_account = "myuser"
+login_password = "mypassword"
+
+REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1/')
+
+# Login
+try:
+ REDFISH_OBJ.login(auth="session")
+except ServerDownOrUnreachableError as excp:
+ sys.stderr.write("Error: server not reachable or does not support RedFish.\n")
+ sys.exit()
+
+# Get the system information /redfish/v1/Systems/1/SmartStorage/
+# /redfish/v1/Systems/1/Processors/
+# /redfish/v1/Systems/1/Memory/proc1dimm1/
+response = REDFISH_OBJ.get(sys.argv[1])
+# Print the system information
+print(response.dict)
+
+# Logout
+REDFISH_OBJ.logout()
--- /dev/null
+from redfish.rest.v1 import ServerDownOrUnreachableError
+import redfish
+import logging
+
+class RedFishClient:
+
+ PREFIX = '/redfish/v1'
+
+ def __init__(self, host, username, password):
+ self.host = host
+ self.username = username
+ self.password = password
+ self.redfish_obj = None
+
+ def login(self):
+ self.redfish_obj = redfish.redfish_client(base_url=self.host,
+ username=self.username,
+ password=self.password,
+ default_prefix=self.PREFIX)
+ try:
+ self.redfish_obj.login(auth="session")
+ except ServerDownOrUnreachableError as e:
+ logging.error(f"Server not reachable or does not support RedFish {e}", e)
+
+ def get_path(self, path):
+ try:
+ if self.PREFIX not in path:
+ path = f"{self.PREFIX}{path}"
+ print(f"getting: {path}")
+ response = self.redfish_obj.get(path)
+ return response.dict
+ except Exception as e:
+ #TODO
+ pass
+
+ def logout(self):
+ self.redfish_obj.logout()
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/EthernetInterfaces/Members/$entity',
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/1/',
+ '@odata.type': '#EthernetInterface.1.0.0.EthernetInterface',
+ 'Id': '1',
+ 'Name': 'System Ethernet Interface',
+ 'Oem': {
+ 'Hp': {
+ '@odata.type': '#HpiLOEthernetNetworkInterface.1.0.0.HpiLOEthernetNetworkInterface',
+ 'DHCPv4': None,
+ 'DHCPv6': None,
+ 'IPv4': None,
+ 'IPv6': None,
+ 'SharedNetworkPortOptions': None
+ }
+ },
+ 'SettingsResult': None,
+ 'Status': None
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/EthernetInterfaces',
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/',
+ '@odata.type': '#EthernetInterfaceCollection.EthernetInterfaceCollection',
+ 'Description': 'Collection of System Network Interfaces',
+ 'Members': [{
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/1/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/2/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/3/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/4/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/5/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/6/'
+ }],
+ 'Members@odata.count': 6,
+ 'Name': 'System Network Interfaces'
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/Memory',
+ '@odata.id': '/redfish/v1/Systems/1/Memory/',
+ '@odata.type': '#HpMemoryCollection.HpMemoryCollection',
+ 'Description': 'Memory DIMM Collection',
+ 'Members': [{
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm1/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm2/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm3/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm4/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm5/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm6/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm7/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm8/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm9/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm10/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm11/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm12/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm1/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm2/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm3/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm4/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm5/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm6/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm7/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm8/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm9/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm10/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm11/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc2dimm12/'
+ }],
+ 'Members@odata.count': 24,
+ 'Name': 'Memory DIMM Collection',
+ 'Oem': {
+ 'Hp': {
+ '@odata.type': '#HpAdvancedMemoryProtection.1.0.0.HpAdvancedMemoryProtection',
+ 'AmpModeActive': 'AdvancedECC',
+ 'AmpModeStatus': 'AdvancedECC',
+ 'AmpModeSupported': ['AdvancedECC', 'OnlineSpareRank']
+ }
+ }
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/Memory/Members/$entity',
+ '@odata.id': '/redfish/v1/Systems/1/Memory/proc1dimm1/',
+ '@odata.type': '#HpMemory.1.0.0.HpMemory',
+ 'DIMMStatus': 'GoodInUse',
+ 'DIMMTechnology': 'RDIMM',
+ 'DIMMType': 'DDR3',
+ 'DataWidth': 64,
+ 'ErrorCorrection': 'SingleBitECC',
+ 'HPMemoryType': 'HPSmartMemory',
+ 'Id': 'proc1dimm1',
+ 'Manufacturer': 'HP ',
+ 'MaximumFrequencyMHz': 1600,
+ 'MinimumVoltageVoltsX10': 13,
+ 'Name': 'proc1dimm1',
+ 'PartNumber': '713756-081 ',
+ 'Rank': 2,
+ 'SizeMB': 16384,
+ 'SocketLocator': 'PROC 1 DIMM 1 ',
+ 'TotalWidth': 72
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/Processors/Members/$entity',
+ '@odata.id': '/redfish/v1/Systems/1/Processors/1/',
+ '@odata.type': '#Processor.1.0.0.Processor',
+ 'Id': '1',
+ 'InstructionSet': 'x86-64',
+ 'Manufacturer': 'Intel',
+ 'MaxSpeedMHz': 4800,
+ 'Model': ' Intel(R) Xeon(R) CPU E5-2640 v2 @ 2.00GHz ',
+ 'Name': 'Processors',
+ 'Oem': {
+ 'Hp': {
+ '@odata.type': '#HpProcessorExt.1.0.0.HpProcessorExt',
+ 'AssetTag': '',
+ 'Cache': [{
+ 'Associativity': '8waySetAssociative',
+ 'CacheSpeedns': 0,
+ 'CurrentSRAMType': ['Burst'],
+ 'EccType': 'SingleBitECC',
+ 'InstalledSizeKB': 256,
+ 'Location': 'Internal',
+ 'MaximumSizeKB': 384,
+ 'Name': 'Processor 1 Internal L1 Cache',
+ 'Policy': 'WriteBack',
+ 'Socketed': False,
+ 'SupportedSRAMType': ['Burst'],
+ 'SystemCacheType': 'Data'
+ }, {
+ 'Associativity': '8waySetAssociative',
+ 'CacheSpeedns': 0,
+ 'CurrentSRAMType': ['Burst'],
+ 'EccType': 'SingleBitECC',
+ 'InstalledSizeKB': 2048,
+ 'Location': 'Internal',
+ 'MaximumSizeKB': 3072,
+ 'Name': 'Processor 1 Internal L2 Cache',
+ 'Policy': 'WriteBack',
+ 'Socketed': False,
+ 'SupportedSRAMType': ['Burst'],
+ 'SystemCacheType': None
+ }, {
+ 'Associativity': '20waySetAssociative',
+ 'CacheSpeedns': 0,
+ 'CurrentSRAMType': ['Burst'],
+ 'EccType': 'SingleBitECC',
+ 'InstalledSizeKB': 20480,
+ 'Location': 'Internal',
+ 'MaximumSizeKB': 30720,
+ 'Name': 'Processor 1 Internal L3 Cache',
+ 'Policy': 'WriteBack',
+ 'Socketed': False,
+ 'SupportedSRAMType': ['Burst'],
+ 'SystemCacheType': None
+ }],
+ 'Characteristics': ['64Bit'],
+ 'ConfigStatus': {
+ 'Populated': True,
+ 'State': 'Enabled'
+ },
+ 'CoresEnabled': 8,
+ 'ExternalClockMHz': 100,
+ 'MicrocodePatches': [{
+ 'CpuId': '0x000206D2',
+ 'Date': '2011-05-03T00:00:00Z',
+ 'PatchId': '0x8000020C'
+ }, {
+ 'CpuId': '0x000206D3',
+ 'Date': '2011-04-20T00:00:00Z',
+ 'PatchId': '0x80000304'
+ }, {
+ 'CpuId': '0x000206D5',
+ 'Date': '2011-10-13T00:00:00Z',
+ 'PatchId': '0x00000513'
+ }, {
+ 'CpuId': '0x000206D6',
+ 'Date': '2018-01-30T00:00:00Z',
+ 'PatchId': '0x0000061C'
+ }, {
+ 'CpuId': '0x000206D7',
+ 'Date': '2018-01-26T00:00:00Z',
+ 'PatchId': '0x00000713'
+ }, {
+ 'CpuId': '0x000306E2',
+ 'Date': '2013-03-21T00:00:00Z',
+ 'PatchId': '0x0000020D'
+ }, {
+ 'CpuId': '0x000306E3',
+ 'Date': '2013-03-21T00:00:00Z',
+ 'PatchId': '0x00000308'
+ }, {
+ 'CpuId': '0x000306E4',
+ 'Date': '2018-01-25T00:00:00Z',
+ 'PatchId': '0x0000042C'
+ }],
+ 'PartNumber': '',
+ 'RatedSpeedMHz': 2000,
+ 'SerialNumber': '',
+ 'VoltageVoltsX10': 14
+ }
+ },
+ 'ProcessorArchitecture': 'x86',
+ 'ProcessorId': {
+ 'EffectiveFamily': '179',
+ 'EffectiveModel': '14',
+ 'IdentificationRegisters': '0x06e40003fbffbfeb',
+ 'MicrocodeInfo': None,
+ 'Step': '4',
+ 'VendorId': 'Intel'
+ },
+ 'ProcessorType': 'CPU',
+ 'Socket': 'Proc 1',
+ 'Status': {
+ 'Health': 'OK'
+ },
+ 'TotalCores': 8,
+ 'TotalThreads': 16
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/Processors',
+ '@odata.id': '/redfish/v1/Systems/1/Processors/',
+ '@odata.type': '#ProcessorCollection.ProcessorCollection',
+ 'Description': 'Processors view',
+ 'Members': [{
+ '@odata.id': '/redfish/v1/Systems/1/Processors/1/'
+ }, {
+ '@odata.id': '/redfish/v1/Systems/1/Processors/2/'
+ }],
+ 'Members@odata.count': 2,
+ 'Name': 'Processors Collection'
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/1/EthernetInterfaces/Members/$entity',
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/1/',
+ '@odata.type': '#EthernetInterface.1.0.0.EthernetInterface',
+ 'Id': '1',
+ 'Name': 'System Ethernet Interface',
+ 'Oem': {
+ 'Hp': {
+ '@odata.type': '#HpiLOEthernetNetworkInterface.1.0.0.HpiLOEthernetNetworkInterface',
+ 'DHCPv4': None,
+ 'DHCPv6': None,
+ 'IPv4': None,
+ 'IPv6': None,
+ 'SharedNetworkPortOptions': None
+ }
+ },
+ 'SettingsResult': None,
+ 'Status': None
+}
--- /dev/null
+{
+ '@odata.context': '/redfish/v1/$metadata#Systems/Members/$entity',
+ '@odata.id': '/redfish/v1/Systems/1/',
+ '@odata.type': '#ComputerSystem.1.0.1.ComputerSystem',
+ 'Actions': {
+ '#ComputerSystem.Reset': {
+ 'ResetType@Redfish.AllowableValues': ['On', 'ForceOff', 'ForceRestart', 'Nmi', 'PushPowerButton'],
+ 'target': '/redfish/v1/Systems/1/Actions/ComputerSystem.Reset/'
+ }
+ },
+ 'AssetTag': ' ',
+ 'BiosVersion': 'P71 01/22/2018',
+ 'Boot': {
+ 'BootSourceOverrideEnabled': 'Disabled',
+ 'BootSourceOverrideSupported': ['None', 'Floppy', 'Cd', 'Hdd', 'Usb', 'Utilities', 'BiosSetup', 'Pxe'],
+ 'BootSourceOverrideTarget': 'None'
+ },
+ 'Description': 'Computer System View',
+ 'EthernetInterfaces': {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/'
+ },
+ 'HostName': 'hive1',
+ 'Id': '1',
+ 'IndicatorLED': 'Off',
+ 'Links': {
+ 'Chassis': [{
+ '@odata.id': '/redfish/v1/Chassis/1/'
+ }],
+ 'ManagedBy': [{
+ '@odata.id': '/redfish/v1/Managers/1/'
+ }]
+ },
+ 'LogServices': {
+ '@odata.id': '/redfish/v1/Systems/1/LogServices/'
+ },
+ 'Manufacturer': 'HPE',
+ 'MemorySummary': {
+ 'Status': {
+ 'HealthRollup': 'OK'
+ },
+ 'TotalSystemMemoryGiB': 384
+ },
+ 'Model': 'ProLiant DL360p Gen8',
+ 'Name': 'Computer System',
+ 'Oem': {
+ 'Hp': {
+ '@odata.type': '#HpComputerSystemExt.1.2.2.HpComputerSystemExt',
+ 'Actions': {
+ '#HpComputerSystemExt.PowerButton': {
+ 'PushType@Redfish.AllowableValues': ['Press', 'PressAndHold'],
+ 'target': '/redfish/v1/Systems/1/Actions/Oem/Hp/ComputerSystemExt.PowerButton/'
+ },
+ '#HpComputerSystemExt.SystemReset': {
+ 'ResetType@Redfish.AllowableValues': ['ColdBoot', 'AuxCycle'],
+ 'target': '/redfish/v1/Systems/1/Actions/Oem/Hp/ComputerSystemExt.SystemReset/'
+ }
+ },
+ 'Bios': {
+ 'Backup': {
+ 'Date': '07/01/2015',
+ 'Family': 'P71',
+ 'VersionString': 'P71 07/01/2015'
+ },
+ 'Bootblock': {
+ 'Date': '03/05/2013',
+ 'Family': 'P71',
+ 'VersionString': 'P71 03/05/2013'
+ },
+ 'Current': {
+ 'Date': '01/22/2018',
+ 'Family': 'P71',
+ 'VersionString': 'P71 01/22/2018'
+ },
+ 'UefiClass': 0
+ },
+ 'DeviceDiscoveryComplete': {
+ 'AMSDeviceDiscovery': 'NoAMS',
+ 'DeviceDiscovery': 'vMainDeviceDiscoveryComplete',
+ 'SmartArrayDiscovery': 'Complete'
+ },
+ 'IntelligentProvisioningIndex': 3,
+ 'IntelligentProvisioningLocation': 'System Board',
+ 'IntelligentProvisioningVersion': 'N/A',
+ 'Links': {
+ 'BIOS': {
+ '@odata.id': '/redfish/v1/Systems/1/Bios/'
+ },
+ 'EthernetInterfaces': {
+ '@odata.id': '/redfish/v1/Systems/1/EthernetInterfaces/'
+ },
+ 'FirmwareInventory': {
+ '@odata.id': '/redfish/v1/Systems/1/FirmwareInventory/'
+ },
+ 'Memory': {
+ '@odata.id': '/redfish/v1/Systems/1/Memory/'
+ },
+ 'NetworkAdapters': {
+ '@odata.id': '/redfish/v1/Systems/1/NetworkAdapters/'
+ },
+ 'PCIDevices': {
+ '@odata.id': '/redfish/v1/Systems/1/PCIDevices/'
+ },
+ 'PCISlots': {
+ '@odata.id': '/redfish/v1/Systems/1/PCISlots/'
+ },
+ 'SmartStorage': {
+ '@odata.id': '/redfish/v1/Systems/1/SmartStorage/'
+ },
+ 'SoftwareInventory': {
+ '@odata.id': '/redfish/v1/Systems/1/SoftwareInventory/'
+ }
+ },
+ 'PostState': 'FinishedPost',
+ 'PowerAllocationLimit': 1500,
+ 'PowerAutoOn': 'Restore',
+ 'PowerOnDelay': 'Minimum',
+ 'PowerRegulatorMode': 'Dynamic',
+ 'PowerRegulatorModesSupported': ['OSControl', 'Dynamic', 'Max', 'Min'],
+ 'TrustedModules': [{
+ 'Status': 'NotPresent'
+ }],
+ 'VirtualProfile': 'Inactive'
+ }
+ },
+ 'PowerState': 'On',
+ 'ProcessorSummary': {
+ 'Count': 2,
+ 'Model': ' Intel(R) Xeon(R) CPU E5-2640 v2 @ 2.00GHz ',
+ 'Status': {
+ 'HealthRollup': 'OK'
+ }
+ },
+ 'Processors': {
+ '@odata.id': '/redfish/v1/Systems/1/Processors/'
+ },
+ 'SKU': '654081-B21 ',
+ 'SerialNumber': 'CZJ4320228 ',
+ 'Status': {
+ 'Health': 'Warning',
+ 'State': 'Enabled'
+ },
+ 'SystemType': 'Physical',
+ 'UUID': '30343536-3138-5A43-4A34-333230323238'
+}
\ No newline at end of file
--- /dev/null
+from system import System
+from redfish_client import RedFishClient
+from threading import Thread
+from time import sleep
+
+class RedfishSystem(System):
+ def __init__(self, host, username, password):
+ self.client = RedFishClient(host, username, password)
+ self.client.login()
+ self._system = {}
+ self.run = False
+ self.thread = None
+
+ def get_system(self):
+ return self._system
+
+ def get_status(self):
+ return self._system['Status']
+
+ def get_metadata(self):
+ return self._system['metadata']
+
+ def get_memory(self):
+ return self._system['memory']
+
+ def get_power(self):
+ return self._system['power']
+
+ def get_processor(self):
+ return self._system['processor']
+
+ def get_network(self):
+ return self._system['network']
+
+ def get_storage(self):
+ return self._system['storage']
+
+ def _process_redfish_system(self, redfish_system):
+ return redfish_system
+
+ def _update_system(self):
+ redfish_system = self.client.get_path('/Systems/1')
+ self._system = self._process_redfish_system(redfish_system)
+
+ def _update_metadata(self):
+ print("Updating metadata")
+ pass
+
+ def _update_memory(self):
+ print("Updating memory")
+ pass
+
+ def _update_power(self):
+ print("Updating power")
+ pass
+
+ def _update_network(self):
+ print("Updating network")
+ net_path = self._system['EthernetInterfaces']['@odata.id']
+ network_info = self.client.get_path(net_path)
+ self._system['network'] = {}
+ for interface in network_info['Members']:
+ interface_path = interface['@odata.id']
+ interface_info = self.client.get_path(interface_path)
+ self._system['network'][interface_info['Id']] = interface_info
+
+ def _update_storage(self):
+ print("Updating storage")
+ pass
+
+ def start_update_loop(self):
+ self.run = True
+ self.thread = Thread(target=self.update)
+ self.thread.start()
+
+ def stop_update_loop(self):
+ self.run = False
+ self.thread.join()
+
+ def update(self):
+ # this loop can have:
+ # - caching logic
+ while self.run:
+ self._update_system()
+ # following calls in theory can be done in parallel
+ self._update_metadata()
+ self._update_memory()
+ self._update_power()
+ self._update_network()
+ self._update_storage()
+ sleep(3)
--- /dev/null
+from threading import Thread
+import requests
+import time
+
+class Reporter:
+ def __init__(self, system, observer_url):
+ self.system = system
+ self.observer_url = observer_url
+ self.finish = False
+
+ def stop(self):
+ self.finish = True
+ self.thread.join()
+
+ def run(self):
+ self.thread = Thread(target=self.loop)
+ self.thread.start()
+
+ def loop(self):
+ while not self.finish:
+ # Any logic to avoid sending the all the system
+ # information every loop can go here. In a real
+ # scenario probably we should just send the sub-parts
+ # that have changed to minimize the traffic in
+ # dense clusters
+ d = self.system.get_system()
+ requests.post(self.observer_url, json=d)
+ time.sleep(10)
--- /dev/null
+from flask import Flask, request, jsonify
+from system import System
+from redfish_system import RedfishSystem
+from reporter import Reporter
+import time
+
+# must be passed as arguments
+host = "https://x.x.x.x:8443"
+username = "myuser"
+password = "mypassword"
+
+# create the redfish system and the obsever
+system = RedfishSystem(host, username, password)
+reporter_agent = Reporter(system, "http://127.0.0.1:8000")
+
+app = Flask(__name__)
+
+@app.route('/system', methods=['GET'])
+def get_system():
+ return jsonify({'system': system.get_system()})
+
+@app.route('/system/memory', methods=['GET'])
+def get_system_memory():
+ return jsonify({'memory': system.get_memory()})
+
+@app.route('/system/network', methods=['GET'])
+def get_system_network():
+ return jsonify({'network': system.get_network()})
+
+@app.route('/system/status', methods=['GET'])
+def get_system_status():
+ return jsonify({'status': system.get_status()})
+
+@app.route('/system/actions/', methods=['POST'])
+def post_system():
+ pass
+
+@app.route('/system/actions/', methods=['PUT'])
+def put_system():
+ pass
+
+@app.route('/system/control/', methods=['DELETE'])
+def delete():
+ pass
+
+if __name__ == '__main__':
+ system.start_update_loop()
+ reporter_agent.run()
+ app.run(debug=True)
--- /dev/null
+
+
+class System:
+ def __init__(self):
+ self._system = {}
+
+ def get_system(self):
+ return self._system
+
+ def get_status(self):
+ return self._system['status']
+
+ def get_metadata(self):
+ return self._system['metadata']
+
+ def get_processor(self):
+ return self._system['processor']
+
+ def get_memory(self):
+ return self._system['memory']
+
+ def get_power(self):
+ return self._system['power']
+
+ def get_network(self):
+ return self._system['network']
+
+ def get_storage(self):
+ return self._system['storage']