Файловый менеджер - Редактировать - /var/opt/nydus/ops/primordial/zkconfig.py
Назад
# -*- coding: utf-8 -*- import re import socket from collections import deque from typing import Any from kazoo.client import KazooClient from kazoo.exceptions import ConnectionLoss, NoNodeError, ZookeeperError from kazoo.handlers.threading import KazooTimeoutError from primordial.config import Config from primordial.utils import retry_this class ZKConfig(Config): """Config class that loads configuration options from a ZooKeeper cluster""" ROOT = '/config' # type: str # The ? in the first capture is so the regex matching is non-greedy. # Passwords with a "=" in them can otherwise result in weird parsing CONFIG_LINE = re.compile(r'\s*(\S+?)\s*=\s*(\S+)\s*') def __init__(self, hosts: str) -> None: self._client = KazooClient(hosts=hosts, read_only=True) self._config = {} # type: ignore self.load_config() def __enter__(self): """ This turns this class/object into a context manager for connections to the zookeeper cluster. This starts up the connection and returns the client as the resource being managed. """ # If start throws an error it will get propagated up the stack # The start method can throw a KazooTimeoutError error self._client.start() return self._client def __exit__(self, _exc_type, _exc_val, _exc_tb): """ This method takes care of releasing the client connection to the zookeeper cluster. """ try: self._client.stop() self._client.close() except Exception: # pylint: disable=W0703 # Squelch any exception we may encounter as part of connection closing pass @retry_this(on_ex_classes=(ConnectionLoss, KazooTimeoutError, socket.error, NoNodeError, ZookeeperError)) def load_config(self): """ Load HFS config data including config at the various namespaces and flatten it out into a dict representation. """ with self as zk_client: for path in self.enumerate(zk_client): self._config.update(self.get_config_at_path(zk_client, path)) def enumerate(self, zk_client): """ Generate all child paths, starting at a particular path. The starting path is also included in this enumeration. """ paths_to_traverse = deque([self.ROOT]) # Do a breadth first traversal of nodes while paths_to_traverse: path = paths_to_traverse.popleft() yield path for child in zk_client.get_children(path): child_path = '{}/{}'.format(path, child) paths_to_traverse.append(child_path) def get_config_at_path(self, zk_client, path): """ Get the data (which is interpreted as config uploaded to that path/namespace) at a particular zookeeper path. Parse out the data looking for lines that look like key=value. Generate a dict out of this normalizing the key appropriately. Finally return back this dict. """ config = {} # The path is going to have /config as the prefix, so when we split on '/' the first 2 items # are '' and 'config'. Hence, we drop the first 2 items in the code below. # Example 1: if path was '/config' then path_sections would be [] # Example 2: if path was '/config/hhfs/nydus' then path_sections would be ['hhfs', 'nydus'] path_sections = path.split('/')[2:] zk_value, _zk_stat = zk_client.get(path) stored_config = zk_value.decode("utf-8") for line in stored_config.split('\n'): match = self.CONFIG_LINE.match(line) if match: k, v = match.groups() config_key = '.'.join(path_sections + [k]) config[config_key] = v return config def get(self, key: str, default: Any = None) -> Any: """ Get the config option as a string :param key: config option name :param default: default value if no value exists in the config :return: option value """ return self._config.get(key, default)
| ver. 1.4 |
Github
|
.
| PHP 8.0.30 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка