From 3679dcaf1e04a562e95238a7060f859cf68eb68f Mon Sep 17 00:00:00 2001 From: Redouane Kachach Date: Wed, 8 Mar 2023 15:27:57 +0100 Subject: [PATCH] First hardware-monitoring draft version Signed-off-by: Redouane Kachach (cherry picked from commit 1c402576529edafdb8aa0aef241965e06fa4c151) --- src/cephadm/node-proxy/data.py | 93 +++++++++++ .../fake_cephadm/cephadm_mgr_module.py | 51 +++++++ src/cephadm/node-proxy/main.py | 12 ++ src/cephadm/node-proxy/redfish-test.py | 27 ++++ src/cephadm/node-proxy/redfish_client.py | 37 +++++ .../redfish_json_samples/interface_sample | 19 +++ .../redfish_json_samples/interfaces_sample | 21 +++ .../node-proxy/redfish_json_samples/memory | 65 ++++++++ .../redfish_json_samples/memory_socket | 21 +++ .../node-proxy/redfish_json_samples/processor | 117 ++++++++++++++ .../redfish_json_samples/processors | 13 ++ .../redfish_json_samples/storage_sample | 19 +++ .../node-proxy/redfish_json_samples/system | 144 ++++++++++++++++++ src/cephadm/node-proxy/redfish_system.py | 91 +++++++++++ src/cephadm/node-proxy/reporter.py | 28 ++++ src/cephadm/node-proxy/server.py | 49 ++++++ src/cephadm/node-proxy/system.py | 29 ++++ 17 files changed, 836 insertions(+) create mode 100644 src/cephadm/node-proxy/data.py create mode 100644 src/cephadm/node-proxy/fake_cephadm/cephadm_mgr_module.py create mode 100644 src/cephadm/node-proxy/main.py create mode 100644 src/cephadm/node-proxy/redfish-test.py create mode 100644 src/cephadm/node-proxy/redfish_client.py create mode 100644 src/cephadm/node-proxy/redfish_json_samples/interface_sample create mode 100644 src/cephadm/node-proxy/redfish_json_samples/interfaces_sample create mode 100644 src/cephadm/node-proxy/redfish_json_samples/memory create mode 100644 src/cephadm/node-proxy/redfish_json_samples/memory_socket create mode 100644 src/cephadm/node-proxy/redfish_json_samples/processor create mode 100644 src/cephadm/node-proxy/redfish_json_samples/processors create mode 100644 src/cephadm/node-proxy/redfish_json_samples/storage_sample create mode 100644 src/cephadm/node-proxy/redfish_json_samples/system create mode 100644 src/cephadm/node-proxy/redfish_system.py create mode 100644 src/cephadm/node-proxy/reporter.py create mode 100644 src/cephadm/node-proxy/server.py create mode 100644 src/cephadm/node-proxy/system.py diff --git a/src/cephadm/node-proxy/data.py b/src/cephadm/node-proxy/data.py new file mode 100644 index 0000000000000..b8e69f39078ba --- /dev/null +++ b/src/cephadm/node-proxy/data.py @@ -0,0 +1,93 @@ + +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': '', + } + ] + }, +} diff --git a/src/cephadm/node-proxy/fake_cephadm/cephadm_mgr_module.py b/src/cephadm/node-proxy/fake_cephadm/cephadm_mgr_module.py new file mode 100644 index 0000000000000..6d46de40dd228 --- /dev/null +++ b/src/cephadm/node-proxy/fake_cephadm/cephadm_mgr_module.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +License: MIT License +Copyright (c) 2023 Miel Donkers + +Very simple HTTP server in python for logging requests +Usage:: + ./server.py [] +""" +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() diff --git a/src/cephadm/node-proxy/main.py b/src/cephadm/node-proxy/main.py new file mode 100644 index 0000000000000..45cd573192a94 --- /dev/null +++ b/src/cephadm/node-proxy/main.py @@ -0,0 +1,12 @@ +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() diff --git a/src/cephadm/node-proxy/redfish-test.py b/src/cephadm/node-proxy/redfish-test.py new file mode 100644 index 0000000000000..3aaab2d2f097d --- /dev/null +++ b/src/cephadm/node-proxy/redfish-test.py @@ -0,0 +1,27 @@ +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() diff --git a/src/cephadm/node-proxy/redfish_client.py b/src/cephadm/node-proxy/redfish_client.py new file mode 100644 index 0000000000000..f4a06ffc309b1 --- /dev/null +++ b/src/cephadm/node-proxy/redfish_client.py @@ -0,0 +1,37 @@ +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() diff --git a/src/cephadm/node-proxy/redfish_json_samples/interface_sample b/src/cephadm/node-proxy/redfish_json_samples/interface_sample new file mode 100644 index 0000000000000..6d351cfbc61e8 --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/interface_sample @@ -0,0 +1,19 @@ +{ + '@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 +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/interfaces_sample b/src/cephadm/node-proxy/redfish_json_samples/interfaces_sample new file mode 100644 index 0000000000000..811a7720d791a --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/interfaces_sample @@ -0,0 +1,21 @@ +{ + '@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' +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/memory b/src/cephadm/node-proxy/redfish_json_samples/memory new file mode 100644 index 0000000000000..fba0606f750ad --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/memory @@ -0,0 +1,65 @@ +{ + '@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'] + } + } +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/memory_socket b/src/cephadm/node-proxy/redfish_json_samples/memory_socket new file mode 100644 index 0000000000000..283c7d41e143a --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/memory_socket @@ -0,0 +1,21 @@ +{ + '@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 +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/processor b/src/cephadm/node-proxy/redfish_json_samples/processor new file mode 100644 index 0000000000000..bc381fb5185c1 --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/processor @@ -0,0 +1,117 @@ +{ + '@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 +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/processors b/src/cephadm/node-proxy/redfish_json_samples/processors new file mode 100644 index 0000000000000..c2fb740a4cce2 --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/processors @@ -0,0 +1,13 @@ +{ + '@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' +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/storage_sample b/src/cephadm/node-proxy/redfish_json_samples/storage_sample new file mode 100644 index 0000000000000..6d351cfbc61e8 --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/storage_sample @@ -0,0 +1,19 @@ +{ + '@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 +} diff --git a/src/cephadm/node-proxy/redfish_json_samples/system b/src/cephadm/node-proxy/redfish_json_samples/system new file mode 100644 index 0000000000000..5bd20170b235a --- /dev/null +++ b/src/cephadm/node-proxy/redfish_json_samples/system @@ -0,0 +1,144 @@ +{ + '@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 diff --git a/src/cephadm/node-proxy/redfish_system.py b/src/cephadm/node-proxy/redfish_system.py new file mode 100644 index 0000000000000..921b7520640a2 --- /dev/null +++ b/src/cephadm/node-proxy/redfish_system.py @@ -0,0 +1,91 @@ +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) diff --git a/src/cephadm/node-proxy/reporter.py b/src/cephadm/node-proxy/reporter.py new file mode 100644 index 0000000000000..3942f38cb5dfc --- /dev/null +++ b/src/cephadm/node-proxy/reporter.py @@ -0,0 +1,28 @@ +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) diff --git a/src/cephadm/node-proxy/server.py b/src/cephadm/node-proxy/server.py new file mode 100644 index 0000000000000..fc09a4fc8e5a3 --- /dev/null +++ b/src/cephadm/node-proxy/server.py @@ -0,0 +1,49 @@ +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) diff --git a/src/cephadm/node-proxy/system.py b/src/cephadm/node-proxy/system.py new file mode 100644 index 0000000000000..c43bd35ebf0c6 --- /dev/null +++ b/src/cephadm/node-proxy/system.py @@ -0,0 +1,29 @@ + + +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'] -- 2.39.5