InvalidCredentialsError
import redfish
import sys
-from util import logger
+from util import Logger
-log = logger(__name__, level=10)
+log = Logger(__name__)
class RedFishClient:
PREFIX = '/redfish/v1'
def __init__(self, host, username, password):
- log.info(f"redfish client initialization...")
+ log.logger.info("redfish client initialization...")
self.host = host
self.username = username
self.password = password
password=self.password,
default_prefix=self.PREFIX)
try:
+ # TODO: add a retry? check for a timeout setting
self.redfish_obj.login(auth="session")
- log.info(f"Logging to redfish api at {self.host} with user: {self.username}")
+ log.logger.info(f"Logging to redfish api at {self.host} with user: {self.username}")
return self.redfish_obj
except InvalidCredentialsError as e:
- log.error(f"Invalid credentials for {self.username} at {self.host}:\n{e}")
+ log.logger.error(f"Invalid credentials for {self.username} at {self.host}:\n{e}")
except (SessionCreationError, ServerDownOrUnreachableError) as e:
- log.error(f"Server not reachable or does not support RedFish:\n{e}")
+ log.logger.error(f"Server not reachable or does not support RedFish:\n{e}")
sys.exit(1)
def get_path(self, path):
try:
if self.PREFIX not in path:
path = f"{self.PREFIX}{path}"
- log.debug(f"getting: {path}")
+ log.logger.debug(f"getting: {path}")
response = self.redfish_obj.get(path)
return response.dict
except Exception as e:
#TODO
- log.error(f"Error detected.\n{e}")
+ log.logger.error(f"Error detected.\n{e}")
pass
def logout(self):
- log.info('logging out...')
+ log.logger.info('logging out...')
self.redfish_obj.logout()
from redfish_system import RedfishSystem
-from util import logger, normalize_dict
+from util import Logger, normalize_dict
-log = logger(__name__)
+log = Logger(__name__)
class RedfishDell(RedfishSystem):
def _update_network(self):
net_path = self._system['EthernetInterfaces']['@odata.id']
- log.info("Updating network")
+ log.logger.info("Updating network")
network_info = self.client.get_path(net_path)
self._system['network'] = {}
result = dict()
def _update_processors(self):
cpus_path = self._system['Processors']['@odata.id']
- log.info("Updating processors")
+ log.logger.info("Updating processors")
cpus_info = self.client.get_path(cpus_path)
self._system['processors'] = {}
result = dict()
def _update_storage(self):
storage_path = self._system['Storage']['@odata.id']
- log.info("Updating storage")
+ log.logger.info("Updating storage")
storage_info = self.client.get_path(storage_path)
result = dict()
for storage in storage_info['Members']:
self._system['storage'] = normalize_dict(result)
def _update_metadata(self):
- log.info("Updating metadata")
+ log.logger.info("Updating metadata")
pass
def _update_memory(self):
- log.info("Updating memory")
+ log.logger.info("Updating memory")
pass
def _update_power(self):
- log.info("Updating power")
+ log.logger.info("Updating power")
pass
from redfish_client import RedFishClient
from threading import Thread, Lock
from time import sleep
-from util import logger
+from util import Logger
-log = logger(__name__)
+log = Logger(__name__)
class RedfishSystem(System):
def __init__(self, **kw):
+ super().__init__(**kw)
self.host = kw.get('host')
self.username = kw.get('username')
self.password = kw.get('password')
self.system_endpoint = kw.get('system_endpoint', '/Systems/1')
- log.info(f"redfish system initialization, host: {self.host}, user: {self.username}")
+ log.logger.info(f"redfish system initialization, host: {self.host}, user: {self.username}")
self.client = RedFishClient(self.host, self.username, self.password)
+
self._system = {}
self.run = False
self.thread = None
self.lock = Lock()
def start_client(self):
- log.info(f"redfish system initialization, host: {self.host}, user: {self.username}")
+ log.logger.info(f"redfish system initialization, host: {self.host}, user: {self.username}")
self.client = RedFishClient(self.host, self.username, self.password)
self.client.login()
# - caching logic
try:
while self.run:
- log.debug("waiting for a lock.")
+ log.logger.debug("waiting for a lock.")
self.lock.acquire()
- log.debug("lock acquired.")
+ log.logger.debug("lock acquired.")
try:
self._update_system()
# following calls in theory can be done in parallel
sleep(5)
finally:
self.lock.release()
- log.debug("lock released.")
+ log.logger.debug("lock released.")
# Catching 'Exception' is probably not a good idea (devel only)
except Exception as e:
- log.error(f"Error detected, logging out from redfish api.\n{e}")
+ log.logger.error(f"Error detected, logging out from redfish api.\n{e}")
self.client.logout()
raise
from threading import Thread
import requests
import time
-from util import logger
+from util import Logger
-log = logger(__name__, level=10)
+log = Logger(__name__)
class Reporter:
def __init__(self, system, observer_url):
# that have changed to minimize the traffic in
# dense clusters
if self.system.data_ready:
- log.debug("waiting for a lock.")
+ log.logger.debug("waiting for a lock.")
self.system.lock.acquire()
- log.debug("lock acquired.")
+ log.logger.debug("lock acquired.")
if not self.system.get_system() == self.system.previous_data:
- log.info('data has changed since last iteration.')
+ log.logger.info('data has changed since last iteration.')
d = self.system.get_system()
try:
requests.post(f"{self.observer_url}/fake_endpoint", json=d)
except requests.exceptions.RequestException as e:
- log.error(f"The reporter couldn't send data to the mgr: {e}")
+ log.logger.error(f"The reporter couldn't send data to the mgr: {e}")
# Need to add a new parameter 'max_retries' to the reporter if it can't
# send the data for more than x times, maybe the daemon should stop altogether
else:
self.system.previous_data = self.system.get_system()
else:
- log.info('no diff, not sending data to the mgr.')
+ log.logger.info('no diff, not sending data to the mgr.')
self.system.lock.release()
- log.debug("lock released.")
+ log.logger.debug("lock released.")
time.sleep(5)
import cherrypy
from redfish_dell import RedfishDell
from reporter import Reporter
-from util import logger
+from util import Config, Logger
import sys
# for devel purposes
DEVEL_ENV_VARS = ['REDFISH_HOST',
'REDFISH_USERNAME',
'REDFISH_PASSWORD']
+
+DEFAULT_CONFIG = {
+ 'reporter': {
+ 'check_interval': 5,
+ 'push_data_max_retries': 30,
+ },
+ 'system': {
+ 'refresh_interval': 5
+ },
+ 'server': {
+ 'port': 8080,
+ },
+ 'logging': {
+ 'level': 20,
+ }
+}
+
for env_var in DEVEL_ENV_VARS:
if os.environ.get(env_var) is None:
print(f"{env_var} environment variable must be set.")
sys.exit(1)
-log = logger(__name__)
+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.info("Server initialization...")
-system = RedfishDell(host=host, username=username, password=password, system_endpoint='/Systems/System.Embedded.1')
+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")
return 'node-proxy daemon stopped'
+class ConfigReload:
+ exposed = True
+
+ def __init__(self, config):
+ self.config = config
+
+ def POST(self):
+ self.config['node_proxy'].reload()
+ return 'node-proxy config reloaded'
+
+
class API:
exposed = True
shutdown = Shutdown()
start = Start()
stop = Stop()
+ config_reload = ConfigReload(cherrypy.config)
def GET(self):
return 'use /system'
if __name__ == '__main__':
cherrypy.config.update({
- 'server.socket_port': 8080
+ 'node_proxy': config,
+ 'server.socket_port': config.server['port']
})
- config = {'/': {
+ c = {'/': {
'request.methods_with_bodies': ('POST', 'PUT', 'PATCH'),
'request.dispatch': cherrypy.dispatch.MethodDispatcher()
}}
system.start_update_loop()
reporter_agent.run()
- cherrypy.quickstart(API(), config=config)
+ cherrypy.quickstart(API(), config=c)
-from util import Config
-
class System:
def __init__(self, **kw):
self._system = {}
- self.config: Config = kw['config']
+ self.config = kw['config']
def get_system(self):
raise NotImplementedError()
import logging
+import yaml
+import os
-def logger(name, level=logging.INFO):
- logger = logging.getLogger(name)
- logger.setLevel(level)
- handler = logging.StreamHandler()
- handler.setLevel(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):
res = dict()
else:
res[key.lower()] = test_dict[key]
return res
+
+
+class Config:
+
+ def __init__(self,
+ config_file='/etc/ceph/node-proxy.yaml',
+ default_config={}):
+ self.config_file = config_file
+ self.default_config = default_config
+
+ self.load_config()
+
+ def load_config(self):
+ if os.path.exists(self.config_file):
+ with open(self.config_file, 'r') as f:
+ self.config = yaml.safe_load(f)
+ else:
+ self.config = self.default_config
+
+ for k, v in self.default_config.items():
+ if k not in self.config.keys():
+ self.config[k] = v
+
+ for k, v in self.config.items():
+ setattr(self, k, v)
+
+ # TODO: need to be improved
+ for _l in Logger._Logger:
+ _l.logger.setLevel(self.logging['level'])
+ _l.logger.handlers[0].setLevel(self.logging['level'])
+
+ def reload(self, config_file=None):
+ if config_file != '':
+ self.config_file = config_file
+ self.load_config()
+
+
+class Logger:
+ _Logger = []
+
+ def __init__(self, name, level=logging.INFO):
+ self.name = name
+ self.level = level
+
+ Logger._Logger.append(self)
+ self.logger = self.get_logger()
+
+ def get_logger(self):
+ 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