from .db_installer import DBInstaller from loguru import logger from controller.utils import execute import pymysql, yaml, os class TiDBInstaller(DBInstaller): def __init__(self, config_file, config): self.config_file = config_file self.db_url = config["database_url"] self.user_name = config["username"] self.password = config["password"] self.tiup_login_host = config["tiup_login_host"] self.tiup_login_password = config["tiup_login_password"] self.fab_cmd = config["fab_cmd"] self.DB_CONF = "/tmp/topology.yaml" def change_conf(self, parameters): assert isinstance(parameters, dict) # modify global variables host = self.db_url.split("/")[0].split(":")[0] port = int(self.db_url.split("/")[0].split(":")[1]) database = self.db_url.split("/")[1] db = pymysql.connect(host=host, user=self.user_name, password=self.password, port=port, db=database, charset='utf8') cursor = db.cursor() try: for key, value in parameters.items(): # filter config parameters if ',' in key: continue cursor.execute("set @@global.%s=%s" % (key[1:len(key)-1], value)) except Exception as e: logger.error(e) db.rollback() finally: db.close() # modify config parameters # step 1: get cluster config parameters(yaml) task_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tiup_deployment.py') get_config_cmd = "%s -H %s -p '%s' -f %s show_config:config_file=%s " \ "--hide status,running,stdout,user,aborts,warnings" \ % (self.fab_cmd, self.tiup_login_host, self.tiup_login_password, task_file, self.config_file) is_success, topology_str = execute(get_config_cmd) if not is_success: raise RuntimeError(topology_str) data = yaml.load(topology_str, Loader=yaml.FullLoader) # step 2: preprocess cluster_roles = [] for key, value in parameters.items(): if ',' not in key: continue role, instance, name = key[1:len(key)-1].split(',') cluster_roles.append(role) servers = data[role + '_servers'] for s in servers: if 'config' not in s.keys(): s['config'] = {} else: s['config'].clear() # step 3: edit cluster config for key, value in parameters.items(): if ',' not in key: continue role, instance, name = key[1:len(key) - 1].split(',') servers = data[role + '_servers'] for s in servers: if instance == str(s['host']) + ':' + str(s['port']): if type(value) == str: if str.isdigit(value): value = int(value) elif value in ('true', 'false'): value = True if value == 'true' else False s['config'][name] = value with open(self.DB_CONF, 'w') as fw: yaml.dump(data, fw) edit_config_cmd = "%s -H %s -p '%s' -f %s edit_config:config_file=%s,topology_file=%s " \ "--hide status,running,stdout,user,aborts,warnings" \ % (self.fab_cmd, self.tiup_login_host, self.tiup_login_password, task_file, self.config_file, self.DB_CONF) is_success, msg = execute(edit_config_cmd) if not is_success: raise RuntimeError(msg) # step 4: reload cluster config reload_cmd = "%s -H %s -p '%s' -f %s reload:config_file=%s,cluster_roles=%s " \ "--hide status,running,stdout,user,aborts,warnings" % \ (self.fab_cmd, self.tiup_login_host, self.tiup_login_password, task_file, self.config_file, ':'.join(set(cluster_roles))) logger.info("Start to run '%s'" % reload_cmd) is_success, msg = execute(reload_cmd) if not is_success: raise RuntimeError(msg)