]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
node-proxy: create entrypoint main()
authorGuillaume Abrioux <gabrioux@ibm.com>
Fri, 16 Jun 2023 09:13:56 +0000 (11:13 +0200)
committerGuillaume Abrioux <gabrioux@ibm.com>
Thu, 25 Jan 2024 14:51:57 +0000 (14:51 +0000)
This creates a `main()` function in server.py that will be the
entrypoint of node-proxy.

This also implement arg parsing and add a `--config` parameter
to specify the configuration file.

Finally, this introduce a small refactor of class `Config` and class
`Logger` in util.py because there was a circular dependency between them.

Signed-off-by: Guillaume Abrioux <gabrioux@ibm.com>
(cherry picked from commit f2f87f4259bbfe1014f5a2309a82f5b08a8d78d3)

src/cephadm/node-proxy/server-v2.py
src/cephadm/node-proxy/util.py

index f4afba4daa11e0a37d2ec56226ab1266fae00fad..4eef854bea5503df312d762ddfc68959941fdcb1 100644 (file)
@@ -5,6 +5,7 @@ from util import Config, Logger
 from typing import Dict
 from basesystem import BaseSystem
 import sys
+import argparse
 
 # for devel purposes
 import os
@@ -33,133 +34,179 @@ for env_var in DEVEL_ENV_VARS:
         print(f"{env_var} environment variable must be set.")
         sys.exit(1)
 
-config = Config(default_config=DEFAULT_CONFIG)
-
-log = Logger(__name__, level=config.logging['level'])
-# must be passed as arguments
-host = os.environ.get('REDFISH_HOST')
-username = os.environ.get('REDFISH_USERNAME')
-password = os.environ.get('REDFISH_PASSWORD')
-
-# create the redfish system and the obsever
-log.logger.info("Server initialization...")
-system = RedfishDell(host=host,
-                     username=username,
-                     password=password,
-                     system_endpoint='/Systems/System.Embedded.1',
-                     config=config)
-reporter_agent = Reporter(system, "http://127.0.0.1:8000")
-
 
 class Memory:
     exposed = True
 
+    def __init__(self, backend: BaseSystem) -> None:
+        self.backend = backend
+
     @cherrypy.tools.json_out()
     def GET(self) -> Dict[str, Dict[str, Dict]]:
-        return {'memory': system.get_memory()}
+        return {'memory': self.backend.get_memory()}
 
 
 class Network:
     exposed = True
 
+    def __init__(self, backend: BaseSystem) -> None:
+        self.backend = backend
+
     @cherrypy.tools.json_out()
     def GET(self) -> Dict[str, Dict[str, Dict]]:
-        return {'network': system.get_network()}
+        return {'network': self.backend.get_network()}
 
 
 class Processors:
     exposed = True
 
+    def __init__(self, backend: BaseSystem) -> None:
+        self.backend = backend
+
     @cherrypy.tools.json_out()
     def GET(self) -> Dict[str, Dict[str, Dict]]:
-        return {'processors': system.get_processors()}
+        return {'processors': self.backend.get_processors()}
 
 
 class Storage:
     exposed = True
 
+    def __init__(self, backend: BaseSystem) -> None:
+        self.backend = backend
+
     @cherrypy.tools.json_out()
     def GET(self) -> Dict[str, Dict[str, Dict]]:
-        return {'storage': system.get_storage()}
+        return {'storage': self.backend.get_storage()}
 
 
 class Status:
     exposed = True
 
+    def __init__(self, backend: BaseSystem) -> None:
+        self.backend = backend
+
     @cherrypy.tools.json_out()
     def GET(self) -> Dict[str, Dict[str, Dict]]:
-        return {'status': system.get_status()}
+        return {'status': self.backend.get_status()}
 
 
 class System:
     exposed = True
-    memory = Memory()
-    network = Network()
-    processors = Processors()
-    storage = Storage()
-    status = Status()
-    # actions = Actions()
-    # control = Control()
+
+    def __init__(self, backend: BaseSystem) -> None:
+        self.memory = Memory(backend)
+        self.network = Network(backend)
+        self.processors = Processors(backend)
+        self.storage = Storage(backend)
+        self.status = Status(backend)
+        # actions = Actions()
+        # control = Control()
 
 
 class Shutdown:
     exposed = True
 
+    def __init__(self, backend: BaseSystem, reporter: Reporter) -> None:
+        self.backend = backend
+        self.reporter = reporter
+
     def POST(self) -> str:
-        _stop()
+        _stop(self.backend, self.reporter)
         cherrypy.engine.exit()
         return 'Server shutdown...'
 
 
-def _stop() -> None:
-    system.stop_update_loop()
-    system.client.logout()
-    reporter_agent.stop()
+def _stop(backend: BaseSystem, reporter: Reporter) -> None:
+    backend.stop_update_loop()
+    backend.client.logout()
+    reporter.stop()
 
 
 class Start:
     exposed = True
 
+    def __init__(self, backend: BaseSystem, reporter: Reporter) -> None:
+        self.backend = backend
+        self.reporter = reporter
+
     def POST(self) -> str:
-        system.start_client()
-        system.start_update_loop()
-        reporter_agent.run()
+        self.backend.start_client()
+        self.backend.start_update_loop()
+        self.reporter.run()
         return 'node-proxy daemon started'
 
 
 class Stop:
     exposed = True
 
+    def __init__(self, backend: BaseSystem, reporter: Reporter) -> None:
+        self.backend = backend
+        self.reporter = reporter
+
     def POST(self) -> str:
-        _stop()
+        _stop(self.backend, self.reporter)
         return 'node-proxy daemon stopped'
 
 
 class ConfigReload:
     exposed = True
 
-    def __init__(self, config: cherrypy.config) -> None:
+    def __init__(self, config: Config) -> None:
         self.config = config
 
     def POST(self) -> str:
-        self.config['node_proxy'].reload()
+        self.config.reload()
         return 'node-proxy config reloaded'
 
 
 class API:
     exposed = True
 
-    system = System()
-    shutdown = Shutdown()
-    start = Start()
-    stop = Stop()
-    config_reload = ConfigReload(cherrypy.config)
+    def __init__(self,
+                 backend: BaseSystem,
+                 reporter: Reporter,
+                 config: Config) -> None:
+
+        self.system = System(backend)
+        self.shutdown = Shutdown(backend, reporter)
+        self.start = Start(backend, reporter)
+        self.stop = Stop(backend, reporter)
+        self.config_reload = ConfigReload(config)
 
     def GET(self) -> str:
         return 'use /system'
 
 
-if __name__ == '__main__':
+def main() -> None:
+
+    parser = argparse.ArgumentParser(
+        prog='node-proxy',
+    )
+    parser.add_argument(
+        '--config',
+        dest='config',
+        type=str,
+        required=False,
+        default='/etc/ceph/node-proxy.yml'
+    )
+
+    args = parser.parse_args()
+    config = Config(args.config, default_config=DEFAULT_CONFIG)
+
+    log = Logger(__name__, level=config.logging['level'])
+    # must be passed as arguments
+    host = os.environ.get('REDFISH_HOST')
+    username = os.environ.get('REDFISH_USERNAME')
+    password = os.environ.get('REDFISH_PASSWORD')
+
+    # create the redfish system and the obsever
+    log.logger.info("Server initialization...")
+    system = RedfishDell(host=host,
+                         username=username,
+                         password=password,
+                         system_endpoint='/Systems/System.Embedded.1',
+                         config=config)
+    reporter_agent = Reporter(system, "http://127.0.0.1:8000")
     cherrypy.config.update({
         'node_proxy': config,
         'server.socket_port': config.__dict__['server']['port']
@@ -170,4 +217,8 @@ if __name__ == '__main__':
     }}
     system.start_update_loop()
     reporter_agent.run()
-    cherrypy.quickstart(API(), config=c)
+    cherrypy.quickstart(API(system, reporter_agent, config), config=c)
+
+
+if __name__ == '__main__':
+    main()
index 6420e904876f2f2df209cc5f42c8ca6aecb809e8..112652f7bd769795041685d0143aad781ca53508 100644 (file)
@@ -5,14 +5,26 @@ import time
 from typing import Dict, List, Callable, Any
 
 
-def normalize_dict(test_dict: Dict) -> Dict:
-    res = dict()
-    for key in test_dict.keys():
-        if isinstance(test_dict[key], dict):
-            res[key.lower()] = normalize_dict(test_dict[key])
-        else:
-            res[key.lower()] = test_dict[key]
-    return res
+class Logger:
+    _Logger: List['Logger'] = []
+
+    def __init__(self, name: str, level: int = logging.INFO):
+        self.name = name
+        self.level = level
+
+        Logger._Logger.append(self)
+        self.logger = self.get_logger()
+
+    def get_logger(self) -> logging.Logger:
+        logger = logging.getLogger(self.name)
+        logger.setLevel(self.level)
+        handler = logging.StreamHandler()
+        handler.setLevel(self.level)
+        fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+        handler.setFormatter(fmt)
+        logger.addHandler(handler)
+
+        return logger
 
 
 class Config:
@@ -50,26 +62,17 @@ class Config:
         self.load_config()
 
 
-class Logger:
-    _Logger: List['Logger'] = []
-
-    def __init__(self, name: str, level: int = logging.INFO):
-        self.name = name
-        self.level = level
+log = Logger(__name__)
 
-        Logger._Logger.append(self)
-        self.logger = self.get_logger()
 
-    def get_logger(self) -> logging.Logger:
-        logger = logging.getLogger(self.name)
-        logger.setLevel(self.level)
-        handler = logging.StreamHandler()
-        handler.setLevel(self.level)
-        fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-        handler.setFormatter(fmt)
-        logger.addHandler(handler)
-
-        return logger
+def normalize_dict(test_dict: Dict) -> Dict:
+    res = dict()
+    for key in test_dict.keys():
+        if isinstance(test_dict[key], dict):
+            res[key.lower()] = normalize_dict(test_dict[key])
+        else:
+            res[key.lower()] = test_dict[key]
+    return res
 
 
 def retry(exceptions: Any = Exception, retries: int = 20, delay: int = 1) -> Callable:
@@ -78,12 +81,12 @@ def retry(exceptions: Any = Exception, retries: int = 20, delay: int = 1) -> Cal
             _tries = retries
             while _tries > 1:
                 try:
-                    print("{}".format(_tries))
+                    log.logger.debug("{} {} attempt(s) left.".format(f, _tries - 1))
                     return f(*args, **kwargs)
                 except exceptions:
                     time.sleep(delay)
                     _tries -= 1
-            print("{} has failed after {} tries".format(f, retries))
+            log.logger.warn("{} has failed after {} tries".format(f, retries))
             return f(*args, **kwargs)
         return _retry
     return decorator