self.backend = backend
self.reporter = reporter
self.config = config
- self.socket_port = self.config.__dict__['api']['port'] if not port else port
+ self.socket_port = port if port else self.config.get('api', {}).get('port', 9456)
self.socket_host = addr
self.subscribe()
import socket
from threading import Lock
from ceph_node_proxy.util import Config, get_logger, BaseThread
-from typing import Dict, Any
+from typing import Dict, Any, Optional, Union
from ceph_node_proxy.baseclient import BaseClient
super().__init__()
self.lock: Lock = Lock()
self._system: Dict = {}
- self.config: Config = kw.get('config', {})
+ self.config: Optional[Union[Config, Dict[str, Any]]] = kw.get('config')
self.client: BaseClient
self.log = get_logger(__name__)
from ceph_node_proxy.baseredfishsystem import BaseRedfishSystem
from ceph_node_proxy.redfishdellsystem import RedfishDellSystem
from ceph_node_proxy.reporter import Reporter
-from ceph_node_proxy.util import Config, get_logger, http_req, write_tmp_file, CONFIG
+from ceph_node_proxy.util import Config, DEFAULTS, get_logger, http_req, write_tmp_file
from urllib.error import HTTPError
from typing import Dict, Any, Optional, Type
self.reporter_endpoint: str = kw.get('reporter_endpoint', '/node-proxy/data')
self.cephx = {'cephx': {'name': self.cephx_name,
'secret': self.cephx_secret}}
- self.config = Config('/etc/ceph/node-proxy.yml', config=CONFIG)
+ config_path = kw.get('config_path') or os.environ.get('NODE_PROXY_CONFIG', '/etc/ceph/node-proxy.yml')
+ self.config = Config(config_path, defaults=DEFAULTS)
self.username: str = ''
self.password: str = ''
self.log.warning('No oob details could be loaded, exiting...')
raise SystemExit(1)
try:
- vendor = getattr(self.config, 'system', {}).get('vendor', 'generic')
+ vendor = self.config.get('system', {}).get('vendor', 'generic')
system_cls = REDFISH_SYSTEM_CLASSES.get(vendor, BaseRedfishSystem)
self.system = system_cls(host=oob_details['host'],
port=oob_details['port'],
args = parser.parse_args()
if args.debug:
- CONFIG['logging']['level'] = 10
+ DEFAULTS['logging']['level'] = 10
if not os.path.exists(args.config):
raise Exception(f'No config file found at provided config path: {args.config}')
ca_file = write_tmp_file(root_cert,
prefix_name='cephadm-endpoint-root-cert')
+ config_path = config.get('node_proxy_config') or os.environ.get('NODE_PROXY_CONFIG', '/etc/ceph/node-proxy.yml')
+
node_proxy_mgr = NodeProxyManager(mgr_host=target_ip,
cephx_name=name,
cephx_secret=keyring,
mgr_agent_port=target_port,
ca_path=ca_file.name,
api_ssl_crt=listener_cert,
- api_ssl_key=listener_key)
+ api_ssl_key=listener_key,
+ config_path=config_path)
signal.signal(signal.SIGTERM,
lambda signum, frame: handler(signum, frame, node_proxy_mgr))
node_proxy_mgr.run()
from typing import Dict, Callable, Any, Optional, MutableMapping, Tuple, Union
-CONFIG: Dict[str, Any] = {
+DEFAULTS: Dict[str, Any] = {
'reporter': {
'check_interval': 5,
'push_data_max_retries': 30,
},
'logging': {
'level': logging.INFO,
- }
+ },
}
+def _deep_merge(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
+ result = dict(base)
+ for key, value in override.items():
+ if key in result and isinstance(result[key], dict) and isinstance(value, dict):
+ result[key] = _deep_merge(result[key], value)
+ else:
+ result[key] = value
+ return result
+
+
+def load_config(
+ path: str,
+ defaults: Optional[Dict[str, Any]] = None,
+) -> Dict[str, Any]:
+ defaults = defaults or {}
+ if not os.path.exists(path):
+ return _deep_merge({}, defaults)
+ with open(path, 'r') as f:
+ loaded = yaml.safe_load(f) or {}
+ return _deep_merge(defaults, loaded)
+
+
def get_logger(name: str, level: Union[int, str] = logging.NOTSET) -> logging.Logger:
log_level: Union[int, str] = level
if log_level == logging.NOTSET:
- log_level = CONFIG['logging']['level']
+ log_level = DEFAULTS['logging']['level']
logger = logging.getLogger(name)
logger.setLevel(log_level)
handler = logging.StreamHandler()
class Config:
- def __init__(self,
- config_file: str = '/etc/ceph/node-proxy.yaml',
- config: Dict[str, Any] = {}) -> None:
- self.config_file = config_file
- self.config = config
-
- self.load_config()
-
- def load_config(self) -> None:
- 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.config
-
- for k, v in self.config.items():
- if k not in self.config.keys():
- self.config[k] = v
-
- for k, v in self.config.items():
- setattr(self, k, v)
-
- def reload(self, config_file: str = '') -> None:
- if config_file != '':
- self.config_file = config_file
- self.load_config()
+ def __init__(
+ self,
+ path: str,
+ defaults: Optional[Dict[str, Any]] = None,
+ ) -> None:
+ self.path = path
+ self.defaults = defaults or {}
+ self._data = load_config(self.path, self.defaults)
+
+ def get(self, key: str, default: Any = None) -> Any:
+ return self._data.get(key, default)
+
+ def __getitem__(self, key: str) -> Any:
+ return self._data[key]
+
+ def reload(self, path: Optional[str] = None) -> None:
+ if path is not None:
+ self.path = path
+ self._data = load_config(self.path, self.defaults)
class BaseThread(threading.Thread):