]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
First hardware-monitoring draft version
authorRedouane Kachach <rkachach@redhat.com>
Wed, 8 Mar 2023 14:27:57 +0000 (15:27 +0100)
committerGuillaume Abrioux <gabrioux@ibm.com>
Thu, 25 Jan 2024 14:48:06 +0000 (14:48 +0000)
Signed-off-by: Redouane Kachach <rkachach@redhat.com>
(cherry picked from commit 1c402576529edafdb8aa0aef241965e06fa4c151)

17 files changed:
src/cephadm/node-proxy/data.py [new file with mode: 0644]
src/cephadm/node-proxy/fake_cephadm/cephadm_mgr_module.py [new file with mode: 0644]
src/cephadm/node-proxy/main.py [new file with mode: 0644]
src/cephadm/node-proxy/redfish-test.py [new file with mode: 0644]
src/cephadm/node-proxy/redfish_client.py [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/interface_sample [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/interfaces_sample [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/memory [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/memory_socket [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/processor [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/processors [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/storage_sample [new file with mode: 0644]
src/cephadm/node-proxy/redfish_json_samples/system [new file with mode: 0644]
src/cephadm/node-proxy/redfish_system.py [new file with mode: 0644]
src/cephadm/node-proxy/reporter.py [new file with mode: 0644]
src/cephadm/node-proxy/server.py [new file with mode: 0644]
src/cephadm/node-proxy/system.py [new file with mode: 0644]

diff --git a/src/cephadm/node-proxy/data.py b/src/cephadm/node-proxy/data.py
new file mode 100644 (file)
index 0000000..b8e69f3
--- /dev/null
@@ -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 (file)
index 0000000..6d46de4
--- /dev/null
@@ -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 [<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()
diff --git a/src/cephadm/node-proxy/main.py b/src/cephadm/node-proxy/main.py
new file mode 100644 (file)
index 0000000..45cd573
--- /dev/null
@@ -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 (file)
index 0000000..3aaab2d
--- /dev/null
@@ -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 (file)
index 0000000..f4a06ff
--- /dev/null
@@ -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 (file)
index 0000000..6d351cf
--- /dev/null
@@ -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 (file)
index 0000000..811a772
--- /dev/null
@@ -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 (file)
index 0000000..fba0606
--- /dev/null
@@ -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 (file)
index 0000000..283c7d4
--- /dev/null
@@ -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 (file)
index 0000000..bc381fb
--- /dev/null
@@ -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 (file)
index 0000000..c2fb740
--- /dev/null
@@ -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 (file)
index 0000000..6d351cf
--- /dev/null
@@ -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 (file)
index 0000000..5bd2017
--- /dev/null
@@ -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 (file)
index 0000000..921b752
--- /dev/null
@@ -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 (file)
index 0000000..3942f38
--- /dev/null
@@ -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 (file)
index 0000000..fc09a4f
--- /dev/null
@@ -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 (file)
index 0000000..c43bd35
--- /dev/null
@@ -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']