Skip to content

Commit 5f34740

Browse files
committed
V3.5.0
2 parents e3a991a + c1debbd commit 5f34740

File tree

34 files changed

+812
-219
lines changed

34 files changed

+812
-219
lines changed

_cmd.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,9 +749,15 @@ def init(self, cmd, args, need_deploy_name=True):
749749
return self
750750

751751
def get_obd_namespaces_data(self, obd):
752-
data = {}
752+
data = {
753+
"component": {},
754+
"error_messages": ''
755+
}
756+
comp_data = data['component']
753757
for component, _ in obd.namespaces.items():
754-
data[component] = _.get_variable('run_result')
758+
comp_data[component] = _.get_variable('run_result')
759+
error = obd.stdio.get_error_buffer().read()
760+
data['error_messages'] = error
755761
return data
756762

757763

@@ -1378,6 +1384,7 @@ class ClusterTenantOptimizeCommand(ClusterMirrorCommand):
13781384
def __init__(self):
13791385
super(ClusterTenantOptimizeCommand, self).__init__('optimize','Optimizing existing tenant scenarios')
13801386
self.parser.add_option('-o', '--optimize', type='string', help='Optimize scenarios,the default is consistent with the cluster dimension.\n{express_oltp, complex_oltp, olap, htap, kv}\nSupported since version 4.3.')
1387+
self.parser.add_option('-p', '--tenant-root-password', type='string', help="tenant root password.")
13811388

13821389
def init(self, cmd, args):
13831390
super(ClusterTenantOptimizeCommand, self).init(cmd, args)
@@ -2602,16 +2609,27 @@ def __init__(self):
26022609
super(HostCommand, self).__init__('host', 'Host tools')
26032610
self.register_command(HostPrecheckCommand())
26042611
self.register_command(HostInitCommand())
2612+
self.register_command(HostUserCommand())
2613+
2614+
2615+
class HostUserCommand(MajorCommand):
2616+
2617+
def __init__(self):
2618+
super(HostUserCommand, self).__init__('user', 'Host user tools')
2619+
self.register_command(HostUserInitCommand())
26052620

26062621

26072622
class HostPrecheckCommand(ObdCommand):
26082623

26092624
def __init__(self):
26102625
super(HostPrecheckCommand, self).__init__('precheck', 'Pre check host system parameters')
26112626
self.parser.add_option('-p', '--password', type='str', help="Password of username, default is empty.")
2627+
self.parser.add_option('-u', '--username', type='str', help="Users to be checked (default: ssh user).")
2628+
self.parser.add_option('--ssh-key-file', type='string', help="ssh key file")
2629+
26122630
def init(self, cmd, args):
26132631
super(HostPrecheckCommand, self).init(cmd, args)
2614-
self.parser.set_usage('%s <username> <server ip>' % self.prev_cmd)
2632+
self.parser.set_usage('%s <ssh username> <server ip>' % self.prev_cmd)
26152633
return self
26162634

26172635
def _do_command(self, obd):
@@ -2632,10 +2650,12 @@ class HostInitCommand(ObdCommand):
26322650
def __init__(self):
26332651
super(HostInitCommand, self).__init__('init', 'Init server environment.')
26342652
self.parser.add_option('-p', '--password', type='str', help="Password of username, default is empty.")
2653+
self.parser.add_option('-u', '--username', type='str', help="Users to be checked (default: ssh user).")
2654+
self.parser.add_option('--ssh-key-file', type='string', help="ssh key file")
26352655

26362656
def init(self, cmd, args):
26372657
super(HostInitCommand, self).init(cmd, args)
2638-
self.parser.set_usage('%s <username> <server ip>' % self.prev_cmd)
2658+
self.parser.set_usage('%s <ssh username> <server ip>' % self.prev_cmd)
26392659
return self
26402660

26412661
def _do_command(self, obd):
@@ -2651,6 +2671,18 @@ def _do_command(self, obd):
26512671
return self._show_help()
26522672

26532673

2674+
class HostUserInitCommand(ObdCommand):
2675+
2676+
def __init__(self):
2677+
super(HostUserInitCommand, self).__init__('init', 'Init host user.')
2678+
self.parser.add_option('-u', '--username', type='str', help="username, default is admin.")
2679+
self.parser.add_option('-p', '--password', type='str', help="Password of username.")
2680+
self.parser.add_option('--host', type='str', help="host ip, default is 127.0.0.1.")
2681+
2682+
def _do_command(self, obd):
2683+
return obd.host_user_init()
2684+
2685+
26542686
class DevHostInitCommand(ObdCommand):
26552687

26562688
def __init__(self):

_environ.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
# obdeploy install path. default /usr/obd/
6060
ENV_OBD_INSTALL_PATH = "OBD_INSTALL_PATH"
6161

62-
# obd web idle minite time before shutdown. default 30
62+
# obd web idle minite time before shutdown. default 120
6363
# if you do not want to set idle time, you can set it to "infinity"
6464
ENV_IDLE_TIME_BEFORE_SHUTDOWN_MINITES = "IDLE_TIME_BEFORE_SHUTDOWN_MINITES"
6565

_stdio.py

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ def __init__(self,
403403
self._output_is_tty = False
404404
self._input_is_tty = False
405405
self._exit_buffer = SetBufferIO()
406+
self._error_buffer = SetBufferIO()
406407
self.set_input_stream(input_stream)
407408
self.set_output_stream(output_stream)
408409

@@ -551,6 +552,11 @@ def get_exit_buffer(self):
551552
return self._root_io.get_exit_buffer()
552553
return self._exit_buffer
553554

555+
def get_error_buffer(self):
556+
if self._root_io:
557+
return self._root_io.get_error_buffer()
558+
return self._error_buffer
559+
554560
def _start_buffer_io(self):
555561
if self._root_io:
556562
return False
@@ -811,6 +817,9 @@ def warn(self, msg, *args, **kwargs):
811817
self._print(MsgLevel.WARN, msg, prev_msg=self.WARNING_PREV.format(self.isatty()), *args, **kwargs)
812818

813819
def error(self, msg, *args, **kwargs):
820+
error_buffer = self.get_error_buffer()
821+
error_msg = self.log_masking(str(msg), ip_masking=True)
822+
error_buffer.write(error_msg)
814823
self._print(MsgLevel.ERROR, msg, prev_msg=self.ERROR_PREV.format(self.isatty()), *args, **kwargs)
815824

816825
def critical(self, msg, *args, **kwargs):
@@ -824,18 +833,18 @@ def critical(self, msg, *args, **kwargs):
824833
self.exit(code)
825834

826835
def contains_keys(self, msg):
827-
keywords = ["IDENTIFIED", "PASSWORD", "CONNECT", "EXECUTER", "CLIENT", "PASSWD", "_PASSKEY", "SUDO", "ACCESS_"]
836+
keywords = ["IDENTIFIED", "PASSWORD", "CONNECT", "EXECUTER", "CLIENT", "PASSWD", "_PASSKEY", "SUDO", "ACCESS_", "HOST INIT", "CHPASSWD"]
828837
return any(keyword in msg.upper() for keyword in keywords)
829838

830839
def table_log_masking(self, msg):
831-
regex = r'(\|\s*(http://[^\s]+)\s*\|\s*admin\s*\|\s*)(\S+)(\s*\|\s*active\s*\|)'
840+
regex = r"(\|\s*http://[^\s]+\s*\|\s*\S+\s*\|\s*')([^']*)('\s*\|\s*active\s*\|)"
832841
pattern = re.compile(regex)
833842
str_msg = str(msg)
834843
if 'active' in str_msg:
835844
match = re.search(pattern, str_msg)
836845
if match:
837-
masked_password = "*"*len(match.group(3))
838-
str_msg = pattern.sub(rf"\1{masked_password}\4", str_msg)
846+
masked_password = "*"*len(match.group(2))
847+
str_msg = pattern.sub(rf"\1{masked_password}\3", str_msg)
839848
elif 'access_' in str_msg:
840849
access_regex = r"(access_id=)[^&]*|(access_key=)[^&,| ]*"
841850
access_pattern = re.compile(access_regex)
@@ -853,7 +862,7 @@ def replace_with_stars(match):
853862
def log_masking_static(msg):
854863
def contains_keys(msg):
855864
keywords = ["IDENTIFIED", "PASSWORD", "CONNECT", "EXECUTER", "CLIENT", "PASSWD", "_PASSKEY", "SUDO",
856-
"ACCESS_"]
865+
"ACCESS_", "HOST INIT", "CHPASSWD"]
857866
return any(keyword in msg.upper() for keyword in keywords)
858867

859868
log_regex = [
@@ -891,6 +900,18 @@ def contains_keys(msg):
891900
if "IDENTIFIED BY" in msg:
892901
return desensitize_sql_pwd(msg)
893902

903+
if "host init" in msg:
904+
host_reg = r'(obd host init\s+.*?)(-p\s+)([^\s\'\"\`]+)'
905+
host_pattern = re.compile(host_reg)
906+
if host_pattern.search(msg):
907+
return host_pattern.sub(r'\1\2******', msg)
908+
909+
if "chpasswd" in msg:
910+
chpasswd_reg = r'(echo\s*"[^:]+:)([^"]+)(".*chpasswd)'
911+
chpasswd_pattern = re.compile(chpasswd_reg)
912+
if chpasswd_pattern.search(msg):
913+
return chpasswd_pattern.sub(r'\1******\3', msg)
914+
894915
pwd_args_regex = r"(_password \S+.*args:\s*\[['\"]?)([^\s'\"']+)(['\"]*)"
895916
arg_pattern = re.compile(pwd_args_regex)
896917
if arg_pattern.search(msg):
@@ -910,9 +931,15 @@ def contains_keys(msg):
910931
pwd_pattern = re.compile(echo_pwd_regex)
911932
if pwd_pattern.search(msg):
912933
return pwd_pattern.sub(r"\1******\3", msg)
934+
935+
opts_regex = r'(\'password\':\s*\')([^\']+)(\')'
936+
opts_pattern = re.compile(opts_regex)
937+
if opts_pattern.search(msg):
938+
return opts_pattern.sub(r"\1******\3", msg)
939+
913940
return msg
914941

915-
def log_masking(self, msg):
942+
def log_masking(self, msg, ip_masking=False):
916943
log_regex = [
917944
r"((-P\s*\S+\s+.*?)-p\s*['\"]?)([^\s'\"']+)(['\"]*)",
918945
r"(_PASSWORD\s*(=|to)\s*['\"]*)([^\s'\"']+)(['\"]*)",
@@ -947,7 +974,20 @@ def log_masking(self, msg):
947974

948975
if "IDENTIFIED BY" in msg:
949976
return desensitize_sql_pwd(msg)
950-
977+
978+
if "host init" in msg:
979+
host_reg = r'(obd host init\s+.*?)(-p\s+)([^\s\'\"\`]+)'
980+
host_pattern = re.compile(host_reg)
981+
if host_pattern.search(msg):
982+
return host_pattern.sub(r'\1\2******', msg)
983+
984+
if "chpasswd" in msg:
985+
chpasswd_reg = r'(echo\s*"[^:]+:)([^"]+)(".*chpasswd)'
986+
chpasswd_pattern = re.compile(chpasswd_reg)
987+
if chpasswd_pattern.search(msg):
988+
return chpasswd_pattern.sub(r'\1******\3', msg)
989+
990+
951991
pwd_args_regex = r"(_password \S+.*args:\s*\[['\"]?)([^\s'\"']+)(['\"]*)"
952992
arg_pattern = re.compile(pwd_args_regex)
953993
if arg_pattern.search(msg):
@@ -967,6 +1007,16 @@ def log_masking(self, msg):
9671007
pwd_pattern = re.compile(echo_pwd_regex)
9681008
if pwd_pattern.search(msg):
9691009
return pwd_pattern.sub(r"\1******\3", msg)
1010+
1011+
opts_regex = r'(\'password\':\s*\')([^\']+)(\')'
1012+
opts_pattern = re.compile(opts_regex)
1013+
if opts_pattern.search(msg):
1014+
return opts_pattern.sub(r"\1******\3", msg)
1015+
1016+
if ip_masking:
1017+
ipv4_pattern = r'\b(?:\d{1,3}\.){2}\d{1,3}\.\d{1,3}\b'
1018+
msg = re.sub(ipv4_pattern, "***.***.***.***", msg)
1019+
9701020
return msg
9711021

9721022
def verbose(self, msg, *args, **kwargs):

const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
STAGE_NINTH = 90
126126
STAGE_TENTH = 100
127127

128-
IDLE_TIME_BEFORE_SHUTDOWN_MINITES = 30
128+
IDLE_TIME_BEFORE_SHUTDOWN_MINITES = 120
129129

130130
#obshell task type
131131
TENANT_BACKUP = 'backup'

core.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,6 +2435,7 @@ def create_standby_tenant(self, standby_deploy_name, primary_deploy_name, primar
24352435
return False
24362436

24372437
self.set_repositories(standby_repositories)
2438+
self.search_param_plugin_and_apply(standby_repositories, standby_deploy.deploy_config)
24382439
standby_type = getattr(self.options, 'type')
24392440
if standby_type not in [SERVICE_MODE, LOCATION_MODE]:
24402441
self._call_stdio('error', "The value of type must be 'SERVICE' or 'LOCATION' and cannot be other values")
@@ -6140,6 +6141,7 @@ def precheck_host(self, username, host, dev=False):
61406141
host,
61416142
username,
61426143
password,
6144+
key_filename=getattr(self.options, 'ssh_key_file', None)
61436145
),
61446146
self.stdio
61456147
)
@@ -6154,17 +6156,6 @@ def precheck_host(self, username, host, dev=False):
61546156
workflows = self.get_workflows('precheck')
61556157
if not self.run_workflow(workflows, **{'host_tool': {'host_clients': clients}}):
61566158
return False
6157-
6158-
need_change_servers_vars = self.get_namespace('host_tool').get_return('precheck').get_return('need_change_servers_vars')
6159-
print_data = []
6160-
for v in need_change_servers_vars.values():
6161-
print_data.extend(v)
6162-
if not print_data:
6163-
self._call_stdio('print', FormatText.success('No need to change system parameters'))
6164-
return True
6165-
self._call_stdio('print_list', print_data, ['ip', 'need_change_var', 'current_value', 'target_value'],
6166-
lambda x: [x['server'], x['var'], x['current_value'], x['value']],
6167-
title='System Parameter Change List')
61686159
if dev:
61696160
return 100
61706161
return True
@@ -6179,6 +6170,7 @@ def init_host(self, username, host, dev=False):
61796170
host,
61806171
username,
61816172
password,
6173+
key_filename=getattr(self.options, 'ssh_key_file', None)
61826174
),
61836175
self.stdio
61846176
)
@@ -6191,7 +6183,7 @@ def init_host(self, username, host, dev=False):
61916183
self.set_repositories([host_tool_repository])
61926184

61936185
workflows = self.get_workflows('init')
6194-
if not self.run_workflow(workflows, **{'host_tool': {'host_clients': clients}}):
6186+
if not self.run_workflow(workflows, **{'host_tool': {'host_clients': clients, 'print_recommend_cmd': False}}):
61956187
return False
61966188

61976189
need_reboot_ips = self.get_namespace('host_tool').get_return('init').get_return('need_reboot_ips')
@@ -6202,6 +6194,19 @@ def init_host(self, username, host, dev=False):
62026194
self._call_stdio('print', FormatText.warning('You must reboot the following servers to ensure the ulimit parameters take effect: ({servers}).'.format(servers=','.join(list(need_reboot_ips)))))
62036195
return True
62046196

6197+
def host_user_init(self):
6198+
host_tool_repository = self.repository_manager.get_repository_allow_shadow('host_tool', '1.0')
6199+
self.set_repositories([host_tool_repository])
6200+
6201+
workflows = self.get_workflows('init_user')
6202+
if not self.run_workflow(workflows):
6203+
return False
6204+
6205+
need_reboot_ips = self.get_namespace('host_tool').get_return('init').get_return('need_reboot_ips')
6206+
if need_reboot_ips:
6207+
self._call_stdio('print', FormatText.warning('You must reboot the following servers to ensure the ulimit parameters take effect: ({servers}).'.format(servers=','.join(list(need_reboot_ips)))))
6208+
return True
6209+
62056210
def interactive_deploy(self, name):
62066211

62076212
def signal_handler(sig, frame):

plugins/general/0.1/db_connect.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,14 @@ def connect():
111111
if component in COMPS_OB:
112112
password = global_conf.get("proxyro_password")
113113
elif component in ["obproxy", "obproxy-ce"]:
114-
password = global_conf.get("observer_sys_password")
114+
for comp in COMPS_OB:
115+
if comp in cluster_config.depends:
116+
ob_servers = cluster_config.get_depend_servers(comp)
117+
ob_config = cluster_config.get_depend_config(comp, ob_servers[0])
118+
password = ob_config.get("proxyro_password")
119+
break
120+
else:
121+
password = global_conf.get("observer_sys_password")
115122
if password:
116123
connected = test_connect()
117124
need_password = not connected

plugins/general/0.1/sync_cluster_config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def sync_cluster_config(plugin_context, *args, **kwargs):
3636
cluster_config.update_global_conf('rs_list', depend_rs_list, save=False)
3737

3838
config_map = {
39-
'observer_sys_password': 'proxyro_password',
4039
'cluster_name': 'appname',
4140
'observer_root_password': 'root_password'
4241
}

plugins/general/0.1/telemetry_info_collect.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,20 @@ def obd_revision(*args, **kwargs):
188188

189189
def init_telemetry_data(opt_data):
190190
data = telemetry_base_data()
191-
for component, _ in json.loads(opt_data).items():
192-
for plugin_name, _ in _.items():
193-
plugin_data = {}
194-
plugin_data['component'] = component
195-
plugin_data['name'] = plugin_name
196-
plugin_data['runTime'] = _['time']
197-
plugin_data['runResult'] = _['result']
198-
data['plugins'].append(plugin_data)
191+
for key, value in json.loads(opt_data).items():
192+
if key == 'error_messages':
193+
data['error_messages'] = value
194+
continue
195+
if key == 'component':
196+
comp_data = value
197+
for component, _ in comp_data.items():
198+
for plugin_name, _ in _.items():
199+
plugin_data = {}
200+
plugin_data['component'] = component
201+
plugin_data['name'] = plugin_name
202+
plugin_data['runTime'] = _['time']
203+
plugin_data['runResult'] = _['result']
204+
data['plugins'].append(plugin_data)
199205

200206
return data
201207

@@ -216,6 +222,7 @@ def telemetry_base_data():
216222
data['instances'] = []
217223

218224
data['plugins'] = []
225+
data['error_messages'] = ''
219226
return data
220227

221228

0 commit comments

Comments
 (0)