1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
mariadb-AlanMologorsky a079a2c944 MCOL-5496: Merge CMAPI code to engine repo.
[add] cmapi code to engine
2023-06-07 10:00:16 +03:00

178 lines
5.4 KiB
Python

import configparser
import logging
import threading
from os.path import getmtime
from cmapi_server.constants import DEFAULT_MCS_CONF_PATH, DEFAULT_SM_CONF_PATH
from mcs_node_control.models.node_config import NodeConfig
class Config:
config_file = ''
# params read from the config file
_desired_nodes = []
_active_nodes = []
_inactive_nodes = []
_primary_node = ''
_my_name = None # derived from config file
config_lock = threading.Lock()
last_mtime = 0
die = False
logger = None
def __init__(self, config_file=DEFAULT_MCS_CONF_PATH):
self.config_file = config_file
self.logger = logging.getLogger()
def getDesiredNodes(self):
self.config_lock.acquire()
self.check_reload()
ret = self._desired_nodes
self.config_lock.release()
return ret
def getActiveNodes(self):
self.config_lock.acquire()
self.check_reload()
ret = self._active_nodes
self.config_lock.release()
return ret
def getInactiveNodes(self):
self.config_lock.acquire()
self.check_reload()
ret = self._inactive_nodes
self.config_lock.release()
return ret
def getAllNodes(self):
"""Returns a 3-element tuple describing the status of all nodes.
index 0 = all nodes in the cluster
index 1 = all active nodes
index 2 = all inactive nodes
"""
self.config_lock.acquire()
self.check_reload()
ret = (self._desired_nodes, self._active_nodes, self._inactive_nodes)
self.config_lock.release()
return ret
def getPrimaryNode(self):
self.config_lock.acquire()
self.check_reload()
ret = self._primary_node
self.config_lock.release()
return ret
def is_shared_storage(self, sm_config_file=DEFAULT_SM_CONF_PATH):
"""Check if SM is S3 or not.
:param sm_config_file: path to SM config,
defaults to DEFAULT_SM_CONF_PATH
:type sm_config_file: str, optional
:return: True if SM is S3 otherwise False
:rtype: bool
TODO: remove in next releases, useless?
"""
sm_config = configparser.ConfigParser()
sm_config.read(sm_config_file)
# only LocalStorage or S3 can be returned for now
storage = sm_config.get(
'ObjectStorage', 'service', fallback='LocalStorage'
)
return storage.lower() == 's3'
def check_reload(self):
"""Check config reload.
Returns True if reload happened, False otherwise.
"""
if self.last_mtime != getmtime(self.config_file):
self.load_config()
return True
return False
def who_am_I(self):
self.config_lock.acquire()
self.check_reload()
ret = self._my_name
self.config_lock.release()
return ret
def load_config(self):
try:
node_config = NodeConfig()
root = node_config.get_current_config_root(self.config_file)
last_mtime = getmtime(self.config_file)
except Exception:
self.logger.warning(
f'Failed to parse config file {self.config_file}.',
exc_info=True
)
return False
node_tmp = root.findall('./DesiredNodes/Node')
if len(node_tmp) == 0:
self.logger.warning(
f'The config file {self.config_file} is missing entries '
'in the DesiredNodes section'
)
return False
desired_nodes = [node.text for node in node_tmp]
active_nodes = [
node.text for node in root.findall('./ActiveNodes/Node')
]
inactive_nodes = [
node.text for node in root.findall('./InactiveNodes/Node')
]
node_tmp = root.find('./PrimaryNode')
if node_tmp is None or len(node_tmp.text) == 0:
self.logger.warning(
f'The config file {self.config_file} is missing a valid '
'PrimaryNode entry'
)
return False
primary_node = node_tmp.text
# find my name in this cluster
names = set(node_config.get_network_addresses_and_names())
all_nodes = set(desired_nodes)
intersection = all_nodes & names
if len(intersection) > 1:
my_name = intersection.pop()
self.logger.warning(
'This node has multiple names in the list of desired nodes, '
'was it added more than once? Some things may not work in '
f'this configuration. Using {my_name} as the name for this '
'node.'
)
elif len(intersection) == 0:
self.logger.warning(
'This node has no entry in the list of desired nodes.'
)
my_name = None
elif len(intersection) == 1:
my_name = intersection.pop()
# handles the initial 0-node special case
if my_name == '127.0.0.1':
my_name = None
self.logger.info(f'Loaded the config file, my name is {my_name}')
desired_nodes.sort()
active_nodes.sort()
inactive_nodes.sort()
self._desired_nodes = desired_nodes
self._active_nodes = active_nodes
self._inactive_nodes = inactive_nodes
self._primary_node = primary_node
self.last_mtime = last_mtime
self._my_name = my_name
return True