_cmd.py 80.2 KB
Newer Older
R
Rongfeng Fu 已提交
1

O
oceanbase-admin 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# coding: utf-8
# OceanBase Deploy.
# Copyright (C) 2021 OceanBase
#
# This file is part of OceanBase Deploy.
#
# OceanBase Deploy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OceanBase Deploy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OceanBase Deploy.  If not, see <https://www.gnu.org/licenses/>.


from __future__ import absolute_import, division, print_function

import os
import sys
import time
F
v1.6.0  
frf12 已提交
27
import textwrap
R
Rongfeng Fu 已提交
28
import json
R
Rongfeng Fu 已提交
29
from uuid import uuid1 as uuid, UUID
R
Rongfeng Fu 已提交
30
from optparse import OptionParser, BadOptionError, Option, IndentedHelpFormatter
O
oceanbase-admin 已提交
31 32 33

from core import ObdHome
from _stdio import IO
R
Rongfeng Fu 已提交
34 35
from _lock import LockMode
from tool import DirectoryUtil, FileUtil, NetUtil, COMMAND_ENV
R
Rongfeng Fu 已提交
36
from _errno import DOC_LINK_MSG, LockError
R
Rongfeng Fu 已提交
37
import _environ as ENV
R
Rongfeng Fu 已提交
38 39
from ssh import LocalClient
from const import *
O
oceanbase-admin 已提交
40 41 42


ROOT_IO = IO(1)
F
v1.5.0  
frf12 已提交
43 44

OBD_HOME_PATH = os.path.join(os.environ.get(CONST_OBD_HOME, os.getenv('HOME')), '.obd')
R
Rongfeng Fu 已提交
45
OBDIAG_HOME_PATH = os.path.join(os.environ.get(CONST_OBD_HOME, os.getenv('HOME')), 'oceanbase-diagnostic-tool')
F
v1.5.0  
frf12 已提交
46
COMMAND_ENV.load(os.path.join(OBD_HOME_PATH, '.obd_environ'), ROOT_IO)
F
v1.6.0  
frf12 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72


class OptionHelpFormatter(IndentedHelpFormatter):

    def format_option(self, option):
        result = []
        opts = self.option_strings[option]
        opt_width = self.help_position - self.current_indent - 2
        if len(opts) > opt_width:
            opts = "%*s%s\n" % (self.current_indent, "", opts)
            indent_first = self.help_position
        else:                       # start help on same line as opts
            opts = "%*s%-*s  " % (self.current_indent, "", opt_width, opts)
            indent_first = 0
        result.append(opts)
        if option.help:
            help_text = self.expand_default(option)
            help_lines = help_text.split('\n')
            if len(help_lines) == 1:
                help_lines = textwrap.wrap(help_text, self.help_width)
            result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
            result.extend(["%*s%s\n" % (self.help_position, "", line)
                           for line in help_lines[1:]])
        elif opts[-1] != "\n":
            result.append("\n")
        return "".join(result)
F
v1.5.0  
frf12 已提交
73

O
oceanbase-admin 已提交
74

R
Rongfeng Fu 已提交
75
class AllowUndefinedOptionParser(OptionParser):
F
v1.5.0  
frf12 已提交
76
    IS_TTY = sys.stdin.isatty()
R
Rongfeng Fu 已提交
77 78 79 80 81 82 83 84 85 86 87 88

    def __init__(self,
                usage=None,
                option_list=None,
                option_class=Option,
                version=None,
                conflict_handler="error",
                description=None,
                formatter=None,
                add_help_option=True,
                prog=None,
                epilog=None,
F
v1.6.0  
frf12 已提交
89 90 91
                allow_undefine=True,
                undefine_warn=True
        ):
R
Rongfeng Fu 已提交
92 93 94 95 96
        OptionParser.__init__(
            self, usage, option_list, option_class, version, conflict_handler,
            description, formatter, add_help_option, prog, epilog
        )
        self.allow_undefine = allow_undefine
F
v1.6.0  
frf12 已提交
97
        self.undefine_warn = undefine_warn
R
Rongfeng Fu 已提交
98 99

    def warn(self, msg, file=None):
F
v1.5.0  
frf12 已提交
100 101 102 103
        if self.IS_TTY:
            print("%s %s" % (IO.WARNING_PREV, msg))
        else:
            print('warn: %s' % msg)
R
Rongfeng Fu 已提交
104 105 106

    def _process_long_opt(self, rargs, values):
        try:
F
v1.4.0  
frf12 已提交
107
            value = rargs[0]
R
Rongfeng Fu 已提交
108 109 110
            OptionParser._process_long_opt(self, rargs, values)
        except BadOptionError as e:
            if self.allow_undefine:
F
v1.4.0  
frf12 已提交
111 112
                key = e.opt_str
                value = value[len(key)+1:]
F
frf12 已提交
113
                setattr(values, key.strip('-').replace('-', '_'), value if value != '' else True)
F
v1.6.0  
frf12 已提交
114
                self.undefine_warn and  self.warn(e)
R
Rongfeng Fu 已提交
115 116 117 118 119
            else:
                raise e

    def _process_short_opts(self, rargs, values):
        try:
F
v1.4.0  
frf12 已提交
120
            value = rargs[0]
R
Rongfeng Fu 已提交
121 122 123
            OptionParser._process_short_opts(self, rargs, values)
        except BadOptionError as e:
            if self.allow_undefine:
F
v1.4.0  
frf12 已提交
124 125
                key = e.opt_str
                value = value[len(key)+1:]
F
v1.5.0  
frf12 已提交
126
                setattr(values, key.strip('-').replace('-', '_'),  value if value != '' else True)
F
v1.6.0  
frf12 已提交
127
                self.undefine_warn and self.warn(e)
R
Rongfeng Fu 已提交
128 129 130 131
            else:
                raise e


O
oceanbase-admin 已提交
132 133 134 135 136 137 138 139 140 141
class BaseCommand(object):

    def __init__(self, name, summary):
        self.name = name
        self.summary = summary
        self.args = []
        self.cmds = []
        self.opts = {}
        self.prev_cmd = ''
        self.is_init = False
R
Rongfeng Fu 已提交
142
        self.hidden = False
R
Rongfeng Fu 已提交
143
        self.has_trace = True
R
Rongfeng Fu 已提交
144
        self.parser = AllowUndefinedOptionParser(add_help_option=False)
R
Rongfeng Fu 已提交
145 146
        self.parser.add_option('-h', '--help', action='callback', callback=self._show_help, help='Show help and exit.')
        self.parser.add_option('-v', '--verbose', action='callback', callback=self._set_verbose, help='Activate verbose output.')
O
oceanbase-admin 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

    def _set_verbose(self, *args, **kwargs):
        ROOT_IO.set_verbose_level(0xfffffff)

    def init(self, cmd, args):
        if self.is_init is False:
            self.prev_cmd = cmd
            self.args = args
            self.is_init = True
            self.parser.prog = self.prev_cmd
            option_list = self.parser.option_list[2:]
            option_list.append(self.parser.option_list[0])
            option_list.append(self.parser.option_list[1])
            self.parser.option_list = option_list
        return self

    def parse_command(self):
        self.opts, self.cmds = self.parser.parse_args(self.args)
        return self.opts

    def do_command(self):
        raise NotImplementedError

    def _show_help(self, *args, **kwargs):
        ROOT_IO.print(self._mk_usage())
        self.parser.exit(1)

    def _mk_usage(self):
F
v1.6.0  
frf12 已提交
175
        return self.parser.format_help(OptionHelpFormatter())
O
oceanbase-admin 已提交
176 177 178 179


class ObdCommand(BaseCommand):

F
v1.5.0  
frf12 已提交
180 181
    OBD_PATH = OBD_HOME_PATH
    OBD_INSTALL_PRE = os.environ.get(CONST_OBD_INSTALL_PRE, '/')
R
Rongfeng Fu 已提交
182
    OBD_INSTALL_PATH = os.environ.get(CONST_OBD_INSTALL_PATH, os.path.join(OBD_INSTALL_PRE, 'usr/obd/'))
O
oceanbase-admin 已提交
183 184 185 186 187 188

    def init_home(self):
        version_path = os.path.join(self.OBD_PATH, 'version')
        version_fobj = FileUtil.open(version_path, 'a+', stdio=ROOT_IO)
        version_fobj.seek(0)
        version = version_fobj.read()
R
Rongfeng Fu 已提交
189
        if VERSION != version:
F
v1.6.0  
frf12 已提交
190
            for part in ['plugins', 'config_parser', 'optimize', 'mirror/remote']:
R
Rongfeng Fu 已提交
191 192
                obd_part_dir = os.path.join(self.OBD_PATH, part)
                if DirectoryUtil.mkdir(self.OBD_PATH):
R
Rongfeng Fu 已提交
193
                    root_part_path = os.path.join(self.OBD_INSTALL_PATH, part)
R
Rongfeng Fu 已提交
194 195
                    if os.path.exists(root_part_path):
                        DirectoryUtil.copy(root_part_path, obd_part_dir, ROOT_IO)
O
oceanbase-admin 已提交
196 197 198 199 200 201
            version_fobj.seek(0)
            version_fobj.truncate()
            version_fobj.write(VERSION)
            version_fobj.flush()
        version_fobj.close()

R
Rongfeng Fu 已提交
202 203
    @property
    def dev_mode(self):
R
Rongfeng Fu 已提交
204 205 206 207 208
        return COMMAND_ENV.get(ENV.ENV_DEV_MODE) == "1"

    @property
    def lock_mode(self):
        return COMMAND_ENV.get(ENV.ENV_LOCK_MODE)
F
v1.5.0  
frf12 已提交
209

R
Rongfeng Fu 已提交
210 211 212 213
    @property
    def enable_log(self):
        return True

F
v1.5.0  
frf12 已提交
214
    def parse_command(self):
F
v1.6.0  
frf12 已提交
215 216
        if self.parser.allow_undefine != True:
            self.parser.allow_undefine = self.dev_mode
R
Rongfeng Fu 已提交
217 218
        return super(ObdCommand, self).parse_command()

O
oceanbase-admin 已提交
219 220 221
    def do_command(self):
        self.parse_command()
        self.init_home()
R
Rongfeng Fu 已提交
222 223
        trace_id = uuid()
        ret = False
O
oceanbase-admin 已提交
224 225 226 227
        try:
            log_dir = os.path.join(self.OBD_PATH, 'log')
            DirectoryUtil.mkdir(log_dir)
            log_path = os.path.join(log_dir, 'obd')
R
Rongfeng Fu 已提交
228 229
            if self.enable_log:
                ROOT_IO.init_trace_logger(log_path, 'obd', trace_id)
O
oceanbase-admin 已提交
230
            ROOT_IO.track_limit += 1
R
Rongfeng Fu 已提交
231 232
            ROOT_IO.verbose('cmd: %s' % self.cmds)
            ROOT_IO.verbose('opts: %s' % self.opts)
R
Rongfeng Fu 已提交
233
            obd = ObdHome(home_path=self.OBD_PATH, dev_mode=self.dev_mode, lock_mode=self.lock_mode, stdio=ROOT_IO)
R
Rongfeng Fu 已提交
234 235
            obd.set_options(self.opts)
            obd.set_cmds(self.cmds)
R
Rongfeng Fu 已提交
236
            ret = self._do_command(obd)
R
Rongfeng Fu 已提交
237 238
            if not ret:
                ROOT_IO.print(DOC_LINK_MSG)
O
oceanbase-admin 已提交
239 240
        except NotImplementedError:
            ROOT_IO.exception('command \'%s\' is not implemented' % self.prev_cmd)
R
Rongfeng Fu 已提交
241
        except LockError:
R
Rongfeng Fu 已提交
242
            ROOT_IO.exception('Another app is currently holding the obd lock.')
O
oceanbase-admin 已提交
243 244
        except SystemExit:
            pass
F
v1.5.0  
frf12 已提交
245 246
        except KeyboardInterrupt:
            ROOT_IO.exception('Keyboard Interrupt')
O
oceanbase-admin 已提交
247
        except:
R
Rongfeng Fu 已提交
248 249
            e = sys.exc_info()[1]
            ROOT_IO.exception('Running Error: %s' % e)
R
Rongfeng Fu 已提交
250
        if self.has_trace:
R
Rongfeng Fu 已提交
251
            ROOT_IO.print('Trace ID: %s' % trace_id)
R
Rongfeng Fu 已提交
252
            ROOT_IO.print('If you want to view detailed obd logs, please run: obd display-trace %s' % trace_id)
R
Rongfeng Fu 已提交
253
        return ret
O
oceanbase-admin 已提交
254 255 256 257 258 259 260 261 262 263 264 265 266

    def _do_command(self, obd):
        raise NotImplementedError


class MajorCommand(BaseCommand):

    def __init__(self, name, summary):
        super(MajorCommand, self).__init__(name, summary)
        self.commands = {}

    def _mk_usage(self):
        if self.commands:
R
Rongfeng Fu 已提交
267
            usage = ['%s <command> [options]\n\nAvailable commands:\n' % self.prev_cmd]
O
oceanbase-admin 已提交
268 269 270
            commands = [x for x in self.commands.values() if not (hasattr(x, 'hidden') and x.hidden)]
            commands.sort(key=lambda x: x.name)
            for command in commands:
R
Rongfeng Fu 已提交
271 272
                if command.hidden is False:
                    usage.append("%-14s %s\n" % (command.name, command.summary))
O
oceanbase-admin 已提交
273 274 275 276 277 278 279 280
            self.parser.set_usage('\n'.join(usage))
        return super(MajorCommand, self)._mk_usage()

    def do_command(self):
        if not self.is_init:
            ROOT_IO.error('%s command not init' % self.prev_cmd)
            raise SystemExit('command not init')
        if len(self.args) < 1:
R
Rongfeng Fu 已提交
281
            ROOT_IO.print('You need to give some commands.\n\nTry `obd --help` for more information.')
O
oceanbase-admin 已提交
282 283 284 285 286 287 288 289 290 291
            self._show_help()
            return False
        base, args = self.args[0], self.args[1:]
        if base not in self.commands:
            self.parse_command()
            self._show_help()
            return False
        cmd = '%s %s' % (self.prev_cmd, base)
        ROOT_IO.track_limit += 1
        return self.commands[base].init(cmd, args).do_command()
R
Rongfeng Fu 已提交
292

O
oceanbase-admin 已提交
293 294 295 296
    def register_command(self, command):
        self.commands[command.name] = command


R
Rongfeng Fu 已提交
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
class HiddenObdCommand(ObdCommand):

    def __init__(self, name, summary):
        super(HiddenObdCommand, self).__init__(name, summary)
        self.hidden = self.dev_mode is False


class HiddenMajorCommand(MajorCommand, HiddenObdCommand):

    pass


class DevCommand(HiddenObdCommand):

    def do_command(self):
        if self.hidden:
            ROOT_IO.error('`%s` is a developer command. Please start the developer mode first.\nUse `obd devmode enable` to start the developer mode' % self.prev_cmd)
            return False
        return super(DevCommand, self).do_command()


class DevModeEnableCommand(HiddenObdCommand):

    def __init__(self):
        super(DevModeEnableCommand, self).__init__('enable', 'Enable Dev Mode')

    def _do_command(self, obd):
R
Rongfeng Fu 已提交
324
        if COMMAND_ENV.set(ENV.ENV_DEV_MODE, "1", save=True, stdio=obd.stdio):
R
Rongfeng Fu 已提交
325 326 327 328 329 330 331 332 333 334 335
            obd.stdio.print("Dev Mode: ON")
            return True
        return False


class DevModeDisableCommand(HiddenObdCommand):

    def __init__(self):
        super(DevModeDisableCommand, self).__init__('disable', 'Disable Dev Mode')

    def _do_command(self, obd):
R
Rongfeng Fu 已提交
336
        if COMMAND_ENV.set(ENV.ENV_DEV_MODE, "0", save=True, stdio=obd.stdio):
R
Rongfeng Fu 已提交
337 338 339 340 341 342 343 344 345 346 347 348 349
            obd.stdio.print("Dev Mode: OFF")
            return True
        return False


class DevModeMajorCommand(HiddenMajorCommand):

    def __init__(self):
        super(DevModeMajorCommand, self).__init__('devmode', 'Developer mode switch')
        self.register_command(DevModeEnableCommand())
        self.register_command(DevModeDisableCommand())


F
v1.5.0  
frf12 已提交
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
class EnvironmentSetCommand(HiddenObdCommand):

    def __init__(self):
        super(EnvironmentSetCommand, self).__init__("set", "Set obd environment variable")

    def init(self, cmd, args):
        super(EnvironmentSetCommand, self).init(cmd, args)
        self.parser.set_usage('%s [key] [value]' % self.prev_cmd)
        return self

    def _do_command(self, obd):
        if len(self.cmds) == 2:
            key = self.cmds[0]
            if key in FORBIDDEN_VARS:
                obd.stdio.error("Set the environment variable {} is not allowed.".format(key))
                return False
            return COMMAND_ENV.set(key, self.cmds[1], save=True, stdio=obd.stdio)
        else:
            return self._show_help()


class EnvironmentUnsetCommand(HiddenObdCommand):

    def __init__(self):
        super(EnvironmentUnsetCommand, self).__init__("unset", "Unset obd environment variable")

    def init(self, cmd, args):
        super(EnvironmentUnsetCommand, self).init(cmd, args)
        self.parser.set_usage('%s [key] [value]' % self.prev_cmd)
        return self

    def _do_command(self, obd):
        if len(self.cmds) == 1:
            return COMMAND_ENV.delete(self.cmds[0], save=True, stdio=obd.stdio)
        else:
            return self._show_help()


class EnvironmentShowCommand(HiddenObdCommand):

    def __init__(self):
        super(EnvironmentShowCommand, self).__init__("show", "Show obd environment variables")
        self.parser.add_option('-A', '--all', action="store_true", help="Show all environment variables including system variables")

    def _do_command(self, obd):
        if self.opts.all:
            envs = COMMAND_ENV.copy().items()
        else:
            envs = COMMAND_ENV.show_env().items()
        obd.stdio.print_list(envs, ["Key", "Value"], title="Environ")
        return True


class EnvironmentClearCommand(HiddenObdCommand):

    def __init__(self):
        super(EnvironmentClearCommand, self).__init__("clear", "Clear obd environment variables")

    def _do_command(self, obd):
        return COMMAND_ENV.clear(stdio=obd.stdio)


class EnvironmentMajorCommand(HiddenMajorCommand):

    def __init__(self):
        super(EnvironmentMajorCommand, self).__init__('env', 'Environment variables for OBD')
        self.register_command(EnvironmentSetCommand())
        self.register_command(EnvironmentUnsetCommand())
        self.register_command(EnvironmentShowCommand())
        self.register_command(EnvironmentClearCommand())


R
Rongfeng Fu 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
class TelemetryPostCommand(HiddenObdCommand):

    def __init__(self):
        super(TelemetryPostCommand, self).__init__("post", "Post telemetry data to OceanBase.By default, OBD telemetry is enabled. To disable OBD telemetry, run the `obd env set TELEMETRY_MODE 0` command. To enable OBD telemetry data printing, run `obd env set TELEMETRY_LOG_MODE 1`.")
        self.parser.add_option('-d', '--data', type='string', help="post obd data")

    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    @property
    def enable_log(self):
        if COMMAND_ENV.get(ENV.TELEMETRY_LOG_MODE, default='1') == '0':
            return False
        return True

    def init(self, cmd, args):
        super(TelemetryPostCommand, self).init(cmd, args)
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
        return self

    def _do_command(self, obd):
        return obd.telemetry_post(self.cmds[0])


class TelemetryMajorCommand(HiddenMajorCommand):

    def __init__(self):
        super(TelemetryMajorCommand, self).__init__("telemetry", "Telemetry for OB-Deploy.By default, OBD telemetry is enabled. To disable OBD telemetry, run the `obd env set TELEMETRY_MODE 0` command. To enable OBD telemetry data printing, run `obd env set TELEMETRY_LOG_MODE 1`.")
        self.register_command(TelemetryPostCommand())

    def do_command(self):
        if COMMAND_ENV.get(ENV.TELEMETRY_MODE, default='1') == '1':
            return super(TelemetryMajorCommand, self).do_command()
        else:
            ROOT_IO.critical('Telemetry is disabled. To enable OBD telemetry, run the `obd env set TELEMETRY_MODE 1` command.')
            return False


O
oceanbase-admin 已提交
461 462 463
class MirrorCloneCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
464
        super(MirrorCloneCommand, self).__init__('clone', 'Clone an RPM package to the local mirror repository.')
R
Rongfeng Fu 已提交
465
        self.parser.add_option('-f', '--force', action='store_true', help="Force clone, overwrite the mirror.")
O
oceanbase-admin 已提交
466 467 468

    def init(self, cmd, args):
        super(MirrorCloneCommand, self).init(cmd, args)
R
Rongfeng Fu 已提交
469
        self.parser.set_usage('%s [mirror path] [options]' % self.prev_cmd)
O
oceanbase-admin 已提交
470 471 472 473 474
        return self

    def _do_command(self, obd):
        if self.cmds:
            for src in self.cmds:
R
Rongfeng Fu 已提交
475
                if not obd.add_mirror(src):
O
oceanbase-admin 已提交
476 477 478 479 480 481 482 483 484
                    return False
            return True
        else:
            return self._show_help()


class MirrorCreateCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
485
        super(MirrorCreateCommand, self).__init__('create', 'Create a local mirror by using the local binary file.')
O
oceanbase-admin 已提交
486
        self.parser.conflict_handler = 'resolve'
R
Rongfeng Fu 已提交
487 488 489 490 491
        self.parser.add_option('-n', '--name', type='string', help="Mirror name.")
        self.parser.add_option('-t', '--tag', type='string', help="Mirror tags. Multiple tags are separated with commas.")
        self.parser.add_option('-V', '--version', type='string', help="Mirror version.")
        self.parser.add_option('-p','--path', type='string', help="Mirror path. [./]", default='./')
        self.parser.add_option('-f', '--force', action='store_true', help="Force create, overwrite the mirror.")
O
oceanbase-admin 已提交
492 493 494
        self.parser.conflict_handler = 'error'

    def _do_command(self, obd):
R
Rongfeng Fu 已提交
495
        return obd.create_repository()
O
oceanbase-admin 已提交
496 497 498 499 500


class MirrorListCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
501
        super(MirrorListCommand, self).__init__('list', 'List mirrors.')
O
oceanbase-admin 已提交
502

F
v1.6.0  
frf12 已提交
503 504 505 506 507
    def init(self, cmd, args):
        super(MirrorListCommand, self).init(cmd, args)
        self.parser.set_usage('%s [section name] [options]\n\nExample: %s local' % (self.prev_cmd, self.prev_cmd))
        return self

O
oceanbase-admin 已提交
508 509
    def show_pkg(self, name, pkgs):
        ROOT_IO.print_list(
R
Rongfeng Fu 已提交
510 511
            pkgs,
            ['name', 'version', 'release', 'arch', 'md5'],
O
oceanbase-admin 已提交
512 513 514 515 516 517 518 519 520 521 522 523
            lambda x: [x.name, x.version, x.release, x.arch, x.md5],
            title='%s Package List' % name
        )

    def _do_command(self, obd):
        if self.cmds:
            name = self.cmds[0]
            if name == 'local':
                pkgs = obd.mirror_manager.local_mirror.get_all_pkg_info()
                self.show_pkg(name, pkgs)
                return True
            else:
R
Rongfeng Fu 已提交
524
                repos = obd.mirror_manager.get_mirrors(is_enabled=None)
O
oceanbase-admin 已提交
525
                for repo in repos:
R
Rongfeng Fu 已提交
526
                    if repo.section_name == name:
R
Rongfeng Fu 已提交
527 528 529
                        if not repo.enabled:
                            ROOT_IO.error('Mirror repository %s is disabled.' % name)
                            return False
O
oceanbase-admin 已提交
530 531 532 533 534 535
                        pkgs = repo.get_all_pkg_info()
                        self.show_pkg(name, pkgs)
                        return True
                ROOT_IO.error('No such mirror repository: %s' % name)
                return False
        else:
R
Rongfeng Fu 已提交
536
            repos = obd.mirror_manager.get_mirrors(is_enabled=None)
O
oceanbase-admin 已提交
537
            ROOT_IO.print_list(
R
Rongfeng Fu 已提交
538
                repos,
R
Rongfeng Fu 已提交
539 540
                ['SectionName', 'Type', 'Enabled', 'Avaiable' , 'Update Time'],
                lambda x: [x.section_name, x.mirror_type.value, x.enabled, x.available, time.strftime("%Y-%m-%d %H:%M", time.localtime(x.repo_age))],
O
oceanbase-admin 已提交
541 542
                title='Mirror Repository List'
            )
F
v1.6.0  
frf12 已提交
543
            ROOT_IO.print("Use `obd mirror list <section name>` for more details")
O
oceanbase-admin 已提交
544 545 546 547 548 549
        return True


class MirrorUpdateCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
550
        super(MirrorUpdateCommand, self).__init__('update', 'Update remote mirror information.')
R
Rongfeng Fu 已提交
551

O
oceanbase-admin 已提交
552 553
    def _do_command(self, obd):
        success = True
R
Rongfeng Fu 已提交
554 555 556
        current = int(time.time())
        mirrors = obd.mirror_manager.get_remote_mirrors()
        for mirror in mirrors:
O
oceanbase-admin 已提交
557
            try:
R
Rongfeng Fu 已提交
558 559
                if mirror.enabled and mirror.repo_age < current:
                    success = mirror.update_mirror() and success
O
oceanbase-admin 已提交
560 561 562
            except:
                success = False
                ROOT_IO.stop_loading('fail')
R
Rongfeng Fu 已提交
563
                ROOT_IO.exception('Fail to synchronize mirorr (%s)' % mirror.name)
O
oceanbase-admin 已提交
564 565 566
        return success


R
Rongfeng Fu 已提交
567 568 569 570
class MirrorEnableCommand(ObdCommand):

    def __init__(self):
        super(MirrorEnableCommand, self).__init__('enable', 'Enable remote mirror repository.')
F
v1.5.0  
frf12 已提交
571

R
Rongfeng Fu 已提交
572
    def _do_command(self, obd):
R
Rongfeng Fu 已提交
573 574 575 576
        ret = True
        for name in self.cmds:
            ret = obd.mirror_manager.set_remote_mirror_enabled(name, True) and ret
        return ret
R
Rongfeng Fu 已提交
577 578 579 580 581 582


class MirrorDisableCommand(ObdCommand):

    def __init__(self):
        super(MirrorDisableCommand, self).__init__('disable', 'Disable remote mirror repository.')
F
v1.5.0  
frf12 已提交
583

R
Rongfeng Fu 已提交
584
    def _do_command(self, obd):
R
Rongfeng Fu 已提交
585 586 587 588 589 590 591 592 593
        ret = True
        for name in self.cmds:
            ret = obd.mirror_manager.set_remote_mirror_enabled(name, False) and ret
        return ret

class MirrorAddRepoCommand(ObdCommand):

    def __init__(self):
        super(MirrorAddRepoCommand, self).__init__('add-repo', 'Add remote mirror repository file.')
R
Rongfeng Fu 已提交
594

R
Rongfeng Fu 已提交
595 596 597 598
    def _do_command(self, obd):
        url = self.cmds[0]
        return obd.mirror_manager.add_repo(url)
        
R
Rongfeng Fu 已提交
599

O
oceanbase-admin 已提交
600 601 602
class MirrorMajorCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
603
        super(MirrorMajorCommand, self).__init__('mirror', 'Manage a component repository for OBD.')
O
oceanbase-admin 已提交
604 605 606 607
        self.register_command(MirrorListCommand())
        self.register_command(MirrorCloneCommand())
        self.register_command(MirrorCreateCommand())
        self.register_command(MirrorUpdateCommand())
R
Rongfeng Fu 已提交
608 609
        self.register_command(MirrorEnableCommand())
        self.register_command(MirrorDisableCommand())
R
Rongfeng Fu 已提交
610
        self.register_command(MirrorAddRepoCommand())
O
oceanbase-admin 已提交
611 612


R
Rongfeng Fu 已提交
613 614 615 616
class RepositoryListCommand(ObdCommand):

    def __init__(self):
        super(RepositoryListCommand, self).__init__('list', 'List local repository.')
R
Rongfeng Fu 已提交
617 618 619 620
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
R
Rongfeng Fu 已提交
621 622 623 624

    def show_repo(self, repos, name=None):
        ROOT_IO.print_list(
            repos,
R
Rongfeng Fu 已提交
625
            ['name', 'version', 'release', 'arch', 'md5', 'tags'],
R
Rongfeng Fu 已提交
626
            lambda x: [x.name, x.version, x.release, x.arch, x.md5, ', '.join(x.tags)],
F
v1.5.0  
frf12 已提交
627
            title='%s Local Repository List' % name if name else 'Local Repository List'
R
Rongfeng Fu 已提交
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
        )

    def _do_command(self, obd):
        name = self.cmds[0] if self.cmds else None
        repos = obd.repository_manager.get_repositories_view(name)
        self.show_repo(repos, name)
        return True


class RepositoryMajorCommand(MajorCommand):

    def __init__(self):
        super(RepositoryMajorCommand, self).__init__('repo', 'Manage local repository for OBD.')
        self.register_command(RepositoryListCommand())


O
oceanbase-admin 已提交
644 645 646 647
class ClusterMirrorCommand(ObdCommand):

    def init(self, cmd, args):
        super(ClusterMirrorCommand, self).init(cmd, args)
R
Rongfeng Fu 已提交
648
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
O
oceanbase-admin 已提交
649 650
        return self

R
Rongfeng Fu 已提交
651 652 653 654 655 656 657 658 659 660
    def get_obd_namespaces_data(self, obd):
        data = {}
        for component, _ in obd.namespaces.items():
            data[component] = _.get_variable('run_result')
        return data

    def background_telemetry_task(self, obd):
        data = json.dumps(self.get_obd_namespaces_data(obd))
        LocalClient.execute_command_background(f"nohup obd telemetry post {self.cmds[0]} --data='{data}' >/dev/null 2>&1 &")

O
oceanbase-admin 已提交
661

R
Rongfeng Fu 已提交
662 663 664 665 666 667 668 669 670
class ClusterConfigStyleChange(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterConfigStyleChange, self).__init__('chst', 'Change Deployment Configuration Style')
        self.parser.add_option('-c', '--components', type='string', help="List the components. Multiple components are separated with commas.")
        self.parser.add_option('--style', type='string', help="Preferred Style")

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
671
            return obd.change_deploy_config_style(self.cmds[0])
R
Rongfeng Fu 已提交
672 673 674 675 676 677 678 679 680 681 682 683 684 685
        else:
            return self._show_help()



class ClusterCheckForOCPChange(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterCheckForOCPChange, self).__init__('check4ocp', 'Check Whether OCP Can Take Over Configurations in Use')
        self.parser.add_option('-c', '--components', type='string', help="List the components. Multiple components are separated with commas.")
        self.parser.add_option('-V', '--version', type='string', help="OCP Version", default='3.1.1')

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
686
            return obd.check_for_ocp(self.cmds[0])
R
Rongfeng Fu 已提交
687 688 689 690
        else:
            return self._show_help()


F
v1.6.0  
frf12 已提交
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
class DemoCommand(ClusterMirrorCommand):

    def __init__(self):
        super(DemoCommand, self).__init__('demo', 'Quickly start')
        self.parser.add_option('-c', '--components', type='string', help="List the components. Multiple components are separated with commas. [oceanbase-ce,obproxy-ce,obagent,prometheus,grafana]\nExample: \nstart oceanbase-ce: obd demo -c oceanbase-ce\n"
         + "start -c oceanbase-ce V3.2.3: obd demo -c oceanbase-ce --oceanbase-ce.version=3.2.3\n"
         + "start oceanbase-ce and obproxy-ce: obd demo -c oceanbase-ce,obproxy-ce", default='oceanbase-ce,obproxy-ce,obagent,prometheus,grafana')
        self.parser.allow_undefine = True
        self.parser.undefine_warn = False

    def _do_command(self, obd):
        setattr(self.opts, 'force', True)
        setattr(self.opts, 'clean', True)
        setattr(self.opts, 'force', True)
        setattr(self.opts, 'force_delete', True)
R
Rongfeng Fu 已提交
706 707 708
        obd.set_options(self.opts)
        return obd.demo()

F
v1.6.0  
frf12 已提交
709

R
Rongfeng Fu 已提交
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
class WebCommand(ObdCommand):

    def __init__(self):
        super(WebCommand, self).__init__('web', 'Start obd deploy application as web.')
        self.parser.add_option('-p', '--port', type='int', help="web server listen port", default=8680)

    def _do_command(self, obd):
        from service.app import OBDWeb
        ROOT_IO.print('start OBD WEB in 0.0.0.0:%s' % self.opts.port)
        ROOT_IO.print('please open http://{0}:{1}'.format(NetUtil.get_host_ip(),  self.opts.port))
        try:
            COMMAND_ENV.set(ENV.ENV_DISABLE_PARALLER_EXTRACT, True, stdio=obd.stdio)
            OBDWeb(obd, self.OBD_INSTALL_PATH).start(self.opts.port)
        except KeyboardInterrupt:
            ROOT_IO.print('Keyboard Interrupt')
        except BaseException as e:
            ROOT_IO.exception('Runtime Error %s' % e)
        finally:
            ROOT_IO.print('stop OBD WEB')
        return True
F
v1.6.0  
frf12 已提交
730

R
Rongfeng Fu 已提交
731 732 733 734 735 736
class ClusterAutoDeployCommand(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterAutoDeployCommand, self).__init__('autodeploy', 'Deploy a cluster automatically by using a simple configuration file.')
        self.parser.add_option('-c', '--config', type='string', help="Path to the configuration file.")
        self.parser.add_option('-f', '--force', action='store_true', help="Force autodeploy, overwrite the home_path.")
R
Rongfeng Fu 已提交
737 738
        self.parser.add_option('-C', '--clean', action='store_true', help="Clean the home_path if the directory belong to you.", default=False)
        self.parser.add_option('--generate-consistent-config', '--gcc', action='store_true', help="Generate consistent config")
R
Rongfeng Fu 已提交
739
        self.parser.add_option('-U', '--unuselibrepo', '--ulp', action='store_true', help="Disable OBD from installing the libs mirror automatically.")
A
Amber Zhang 已提交
740
        self.parser.add_option('-A', '--auto-create-tenant', '--act', action='store_true', help="Automatically create a tenant named `test` by using all the available resource of the cluster.")
R
Rongfeng Fu 已提交
741 742 743 744 745
        self.parser.add_option('--force-delete', action='store_true', help="Force delete, delete the registered cluster.")
        self.parser.add_option('-s', '--strict-check', action='store_true', help="Throw errors instead of warnings when check fails.")

    def _do_command(self, obd):
        if self.cmds:
F
v1.5.0  
frf12 已提交
746 747
            if getattr(self.opts, 'force', False) or getattr(self.opts, 'clean', False):
                setattr(self.opts, 'skip_cluster_status_check', True)
R
Rongfeng Fu 已提交
748
                obd.set_options(self.opts)
R
Rongfeng Fu 已提交
749
            name = self.cmds[0]
R
Rongfeng Fu 已提交
750
            if obd.genconfig(name):
R
Rongfeng Fu 已提交
751
                self.opts.config = ''
R
Rongfeng Fu 已提交
752
                obd.set_cmds(self.cmds[1:])
R
Rongfeng Fu 已提交
753 754 755
                res = obd.deploy_cluster(name) and obd.start_cluster(name)
                self.background_telemetry_task(obd)
                return res
R
Rongfeng Fu 已提交
756
            return False
R
Rongfeng Fu 已提交
757 758 759 760
        else:
            return self._show_help()


O
oceanbase-admin 已提交
761 762 763
class ClusterDeployCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
764 765 766
        super(ClusterDeployCommand, self).__init__('deploy', 'Deploy a cluster by using the current deploy configuration or a deploy yaml file.')
        self.parser.add_option('-c', '--config', type='string', help="Path to the configuration yaml file.")
        self.parser.add_option('-f', '--force', action='store_true', help="Force deploy, overwrite the home_path.", default=False)
F
v1.5.0  
frf12 已提交
767
        self.parser.add_option('-C', '--clean', action='store_true', help="Clean the home path if the directory belong to you.", default=False)
R
Rongfeng Fu 已提交
768
        self.parser.add_option('-U', '--unuselibrepo', '--ulp', action='store_true', help="Disable OBD from installing the libs mirror automatically.")
A
Amber Zhang 已提交
769
        self.parser.add_option('-A', '--auto-create-tenant', '--act', action='store_true', help="Automatically create a tenant named `test` by using all the available resource of the cluster.")
O
oceanbase-admin 已提交
770 771 772 773
        # self.parser.add_option('-F', '--fuzzymatch', action='store_true', help="enable fuzzy match when search package")

    def _do_command(self, obd):
        if self.cmds:
F
v1.5.0  
frf12 已提交
774 775
            if getattr(self.opts, 'force', False) or getattr(self.opts, 'clean', False):
                setattr(self.opts, 'skip_cluster_status_check', True)
R
Rongfeng Fu 已提交
776
                obd.set_options(self.opts)
R
Rongfeng Fu 已提交
777 778 779
            res = obd.deploy_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
O
oceanbase-admin 已提交
780 781 782 783 784 785 786
        else:
            return self._show_help()


class ClusterStartCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
787
        super(ClusterStartCommand, self).__init__('start', 'Start a deployed cluster.')
R
Rongfeng Fu 已提交
788 789
        self.parser.add_option('-s', '--servers', type='string', help="List of servers to be started. Multiple servers are separated with commas.")
        self.parser.add_option('-c', '--components', type='string', help="List of components to be started. Multiple components are separated with commas.")
R
Rongfeng Fu 已提交
790 791
        self.parser.add_option('-f', '--force-delete', action='store_true', help="Force delete, delete the registered cluster.")
        self.parser.add_option('-S', '--strict-check', action='store_true', help="Throw errors instead of warnings when check fails.")
R
Rongfeng Fu 已提交
792
        self.parser.add_option('--without-parameter', '--wop', action='store_true', help='Start without parameters.')
O
oceanbase-admin 已提交
793 794 795

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
796
            obd.set_cmds(self.cmds[1:])
R
Rongfeng Fu 已提交
797 798 799
            res = obd.start_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
O
oceanbase-admin 已提交
800 801 802 803 804 805 806
        else:
            return self._show_help()


class ClusterStopCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
807
        super(ClusterStopCommand, self).__init__('stop', 'Stop a started cluster.')
R
Rongfeng Fu 已提交
808 809
        self.parser.add_option('-s', '--servers', type='string', help="List of servers to be stoped. Multiple servers are separated with commas.")
        self.parser.add_option('-c', '--components', type='string', help="List of components to be stoped. Multiple components are separated with commas.")
O
oceanbase-admin 已提交
810 811 812

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
813 814 815
            res = obd.stop_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
O
oceanbase-admin 已提交
816 817 818 819 820 821 822
        else:
            return self._show_help()


class ClusterDestroyCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
823 824
        super(ClusterDestroyCommand, self).__init__('destroy', 'Destroy a deployed cluster.')
        self.parser.add_option('-f', '--force-kill', action='store_true', help="Force kill the running observer process in the working directory.")
O
oceanbase-admin 已提交
825 826 827

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
828 829
            res = obd.destroy_cluster(self.cmds[0])
            return res
O
oceanbase-admin 已提交
830 831 832 833 834 835 836
        else:
            return self._show_help()


class ClusterDisplayCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
837
        super(ClusterDisplayCommand, self).__init__('display', 'Display the information for a cluster.')
O
oceanbase-admin 已提交
838 839 840 841 842 843 844 845 846 847 848

    def _do_command(self, obd):
        if self.cmds:
            return obd.display_cluster(self.cmds[0])
        else:
            return self._show_help()


class ClusterRestartCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
849
        super(ClusterRestartCommand, self).__init__('restart', 'Restart a started cluster.')
R
Rongfeng Fu 已提交
850 851
        self.parser.add_option('-s', '--servers', type='string', help="List of servers to be restarted. Multiple servers are separated with commas.")
        self.parser.add_option('-c', '--components', type='string', help="List of components to be restarted. Multiple components are separated with commas.")
R
Rongfeng Fu 已提交
852
        self.parser.add_option('--with-parameter', '--wp', action='store_true', help='Restart with parameters.')
O
oceanbase-admin 已提交
853 854 855

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
856 857
            if not getattr(self.opts, 'with_parameter', False):
                setattr(self.opts, 'without_parameter', True)
R
Rongfeng Fu 已提交
858
            obd.set_options(self.opts)
R
Rongfeng Fu 已提交
859 860 861
            res = obd.restart_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
O
oceanbase-admin 已提交
862 863 864 865 866 867 868
        else:
            return self._show_help()


class ClusterRedeployCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
869 870
        super(ClusterRedeployCommand, self).__init__('redeploy', 'Redeploy a started cluster.')
        self.parser.add_option('-f', '--force-kill', action='store_true', help="Force kill the running observer process in the working directory.")
O
oceanbase-admin 已提交
871 872 873

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
874 875 876
            res = obd.redeploy_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
O
oceanbase-admin 已提交
877 878 879 880 881 882 883
        else:
            return self._show_help()


class ClusterReloadCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
884
        super(ClusterReloadCommand, self).__init__('reload', 'Reload a started cluster.')
O
oceanbase-admin 已提交
885 886 887

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
888 889 890
            res = obd.reload_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
O
oceanbase-admin 已提交
891 892 893 894 895 896 897
        else:
            return self._show_help()


class ClusterListCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
898
        super(ClusterListCommand, self).__init__('list', 'List all the deployments.')
R
Rongfeng Fu 已提交
899 900 901 902
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
O
oceanbase-admin 已提交
903 904 905 906 907 908 909 910 911 912 913

    def _do_command(self, obd):
        if self.cmds:
            return self._show_help()
        else:
            return obd.list_deploy()


class ClusterEditConfigCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
914
        super(ClusterEditConfigCommand, self).__init__('edit-config', 'Edit the configuration file for a specific deployment.')
O
oceanbase-admin 已提交
915 916 917 918 919 920 921 922

    def _do_command(self, obd):
        if self.cmds:
            return obd.edit_deploy_config(self.cmds[0])
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
923 924 925
class ClusterChangeRepositoryCommand(ClusterMirrorCommand):

    def __init__(self):
F
v1.5.0  
frf12 已提交
926
        super(ClusterChangeRepositoryCommand, self).__init__('reinstall', 'Reinstall a deployed component')
R
Rongfeng Fu 已提交
927 928 929 930 931 932
        self.parser.add_option('-c', '--component', type='string', help="Component name to change repository.")
        self.parser.add_option('--hash', type='string', help="Repository's hash")
        self.parser.add_option('-f', '--force', action='store_true', help="force change even start failed.")

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
933
            return obd.reinstall(self.cmds[0])
R
Rongfeng Fu 已提交
934 935 936 937
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
938 939 940
class CLusterUpgradeCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
941
        super(CLusterUpgradeCommand, self).__init__('upgrade', 'Upgrade a cluster.')
R
Rongfeng Fu 已提交
942 943 944 945 946
        self.parser.add_option('-c', '--component', type='string', help="Component name to upgrade.")
        self.parser.add_option('-V', '--version', type='string', help="Target version.")
        self.parser.add_option('--skip-check', action='store_true', help="Skip all the possible checks.")
        self.parser.add_option('--usable', type='string', help="Hash list for priority mirrors, separated with `,`.", default='')
        self.parser.add_option('--disable', type='string', help="Hash list for disabled mirrors, separated with `,`.", default='')
R
Rongfeng Fu 已提交
947
        self.parser.add_option('-e', '--executer-path', type='string', help="Executer path.", default=os.path.join(ObdCommand.OBD_INSTALL_PATH, 'lib/executer'))
R
Rongfeng Fu 已提交
948
        self.parser.add_option('-t', '--script-query-timeout', type='string', help="The timeout(s) for executing sql in upgrade scripts. Supported since version 4.1.0", default='')
R
Rongfeng Fu 已提交
949 950 951

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
952 953 954
            res = obd.upgrade_cluster(self.cmds[0])
            self.background_telemetry_task(obd)
            return res
R
Rongfeng Fu 已提交
955 956 957
        else:
            return self._show_help()

R
Rongfeng Fu 已提交
958 959 960 961 962

class ClusterTenantCreateCommand(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterTenantCreateCommand, self).__init__('create', 'Create a tenant.')
F
v1.5.0  
frf12 已提交
963
        self.parser.add_option('-t', '-n', '--tenant-name', type='string', help="The tenant name. The default tenant name is [test].", default='test')
R
Rongfeng Fu 已提交
964 965
        self.parser.add_option('--max-cpu', type='float', help="Max CPU unit number.")
        self.parser.add_option('--min-cpu', type='float', help="Mind CPU unit number.")
F
v1.5.0  
frf12 已提交
966 967 968 969 970 971
        self.parser.add_option('--max-memory', type='string', help="Max memory unit size. Not supported after version 4.0, use `--memory-size` instead")
        self.parser.add_option('--min-memory', type='string', help="Min memory unit size. Not supported after version 4.0, use `--memory-size` instead")
        self.parser.add_option('--memory-size', type='string', help="Memory unit size. Supported since version 4.0.")
        self.parser.add_option('--max-disk-size', type='string', help="Max disk unit size. Not supported after version 4.0")
        self.parser.add_option('--log-disk-size', type='string', help="Log disk unit size.")
        self.parser.add_option('--max-iops', type='int', help="Max IOPS unit number.")
R
Rongfeng Fu 已提交
972
        self.parser.add_option('--min-iops', type='int', help="Min IOPS unit number.")
F
v1.5.0  
frf12 已提交
973 974
        self.parser.add_option('--iops-weight', type='int', help="The weight of IOPS. When Max IOPS is greater than Min IOPS, the weight of idle resources available to the current tenant. Supported since version 4.0.")
        self.parser.add_option('--max-session-num', type='int', help="Max session unit number. Not supported after version 4.0")
R
Rongfeng Fu 已提交
975 976
        self.parser.add_option('--unit-num', type='int', help="Pool unit number.")
        self.parser.add_option('-z', '--zone-list', type='string', help="Tenant zone list.")
R
Rongfeng Fu 已提交
977
        self.parser.add_option('--mode', type='string', help='Tenant compatibility mode. {mysql,oracle} [mysql]', default='mysql')
R
Rongfeng Fu 已提交
978 979
        self.parser.add_option('--charset', type='string', help="Tenant charset.")
        self.parser.add_option('--collate', type='string', help="Tenant COLLATE.")
R
Rongfeng Fu 已提交
980
        self.parser.add_option('--replica-num', type='int', help="Tenant replica number.")
R
Rongfeng Fu 已提交
981 982
        self.parser.add_option('--logonly-replica-num', type='int', help="Tenant logonly replica number.")
        self.parser.add_option('--tablegroup', type='string', help="Tenant tablegroup.")
R
Rongfeng Fu 已提交
983
        self.parser.add_option('--primary-zone', type='string', help="Tenant primary zone. [RANDOM].", default='RANDOM')
R
Rongfeng Fu 已提交
984
        self.parser.add_option('--locality', type='string', help="Tenant locality.")
R
Rongfeng Fu 已提交
985
        self.parser.add_option('-s', '--variables', type='string', help="Set the variables for the system tenant. [ob_tcp_invited_nodes='%'].", default="ob_tcp_invited_nodes='%'")
R
Rongfeng Fu 已提交
986 987 988

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
989
            return obd.create_tenant(self.cmds[0])
R
Rongfeng Fu 已提交
990 991 992 993 994 995 996 997
        else:
            return self._show_help()


class ClusterTenantDropCommand(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterTenantDropCommand, self).__init__('drop', 'Drop a tenant.')
F
v1.5.0  
frf12 已提交
998
        self.parser.add_option('-t', '-n', '--tenant-name', type='string', help="Tenant name.")
R
Rongfeng Fu 已提交
999 1000 1001

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
            return obd.drop_tenant(self.cmds[0])
        else:
            return self._show_help()


class ClusterTenantListCommand(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterTenantListCommand, self).__init__('show', 'Show the list of tenant.')

    def _do_command(self, obd):
        if self.cmds:
            return obd.list_tenant(self.cmds[0])
R
Rongfeng Fu 已提交
1015 1016 1017 1018 1019 1020 1021
        else:
            return self._show_help()


class ClusterTenantCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1022
        super(ClusterTenantCommand, self).__init__('tenant', 'Create, drop or list a tenant.')
R
Rongfeng Fu 已提交
1023 1024
        self.register_command(ClusterTenantCreateCommand())
        self.register_command(ClusterTenantDropCommand())
R
Rongfeng Fu 已提交
1025
        self.register_command(ClusterTenantListCommand())
R
Rongfeng Fu 已提交
1026 1027


O
oceanbase-admin 已提交
1028 1029 1030
class ClusterMajorCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1031
        super(ClusterMajorCommand, self).__init__('cluster', 'Deploy and manage a cluster.')
R
Rongfeng Fu 已提交
1032 1033
        self.register_command(ClusterCheckForOCPChange())
        self.register_command(ClusterConfigStyleChange())
R
Rongfeng Fu 已提交
1034
        self.register_command(ClusterAutoDeployCommand())
O
oceanbase-admin 已提交
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
        self.register_command(ClusterDeployCommand())
        self.register_command(ClusterStartCommand())
        self.register_command(ClusterStopCommand())
        self.register_command(ClusterDestroyCommand())
        self.register_command(ClusterDisplayCommand())
        self.register_command(ClusterListCommand())
        self.register_command(ClusterRestartCommand())
        self.register_command(ClusterRedeployCommand())
        self.register_command(ClusterEditConfigCommand())
        self.register_command(ClusterReloadCommand())
R
Rongfeng Fu 已提交
1045
        self.register_command(CLusterUpgradeCommand())
R
Rongfeng Fu 已提交
1046
        self.register_command(ClusterChangeRepositoryCommand())
R
Rongfeng Fu 已提交
1047
        self.register_command(ClusterTenantCommand())
O
oceanbase-admin 已提交
1048 1049 1050 1051 1052 1053


class TestMirrorCommand(ObdCommand):

    def init(self, cmd, args):
        super(TestMirrorCommand, self).init(cmd, args)
R
Rongfeng Fu 已提交
1054
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
O
oceanbase-admin 已提交
1055 1056 1057 1058 1059 1060
        return self


class MySQLTestCommand(TestMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1061
        super(MySQLTestCommand, self).__init__('mysqltest', 'Run a mysqltest for a deployment.')
R
Rongfeng Fu 已提交
1062 1063
        self.parser.add_option('--mode', type='string', help='Test mode. Available values are mysql, oracle, and both.', default='both')
        # self.parser.add_option('--case-mode', type='string', help='case run mode [mysql,oracle]', default='mysql')
R
Rongfeng Fu 已提交
1064
        self.parser.add_option('--component', type='string', help='Components for mysqltest.')
R
Rongfeng Fu 已提交
1065 1066 1067 1068 1069 1070 1071
        self.parser.add_option('--test-server', type='string', help='The server for mysqltest. By default, the first root server in the component is the mysqltest server.')
        self.parser.add_option('--user', type='string', help='Username for a test. [admin]', default='admin')
        self.parser.add_option('--password', type='string', help='Password for a test. [admin]', default='admin')
        self.parser.add_option('--database', type='string', help='Database for a test. [test]', default='test')
        self.parser.add_option('--mysqltest-bin', type='string', help='Mysqltest bin path. [/u01/obclient/bin/mysqltest]', default='/u01/obclient/bin/mysqltest')
        self.parser.add_option('--obclient-bin', type='string', help='OBClient bin path. [obclient]', default='obclient')
        self.parser.add_option('--test-dir', type='string', help='Test case file directory. [./mysql_test/t]', default='./mysql_test/t')
F
v1.5.0  
frf12 已提交
1072
        self.parser.add_option('--test-file-suffix', type='string', help='Test case file suffix. [.test]', default='.test')
R
Rongfeng Fu 已提交
1073
        self.parser.add_option('--result-dir', type='string', help='Result case file directory. [./mysql_test/r]', default='./mysql_test/r')
F
v1.5.0  
frf12 已提交
1074
        self.parser.add_option('--result-file-suffix', type='string', help='Result file suffix. [.result]', default='.result')
F
v1.4.0  
frf12 已提交
1075
        self.parser.add_option('--record', action='store_true', help='record mysqltest execution results', default=False)
F
v1.5.0  
frf12 已提交
1076 1077 1078
        self.parser.add_option('--record-dir', type='string', help='The directory of the result file for mysqltest.', default='./record')
        self.parser.add_option('--record-file-suffix', type='string', help='Result file suffix. [.record]', default='.record')
        self.parser.add_option('--log-dir', type='string', help='The log file directory.')
R
Rongfeng Fu 已提交
1079 1080
        self.parser.add_option('--tmp-dir', type='string', help='Temporary directory for mysqltest. [./tmp]', default='./tmp')
        self.parser.add_option('--var-dir', type='string', help='Var directory to use when run mysqltest. [./var]', default='./var')
O
oceanbase-admin 已提交
1081
        self.parser.add_option('--test-set', type='string', help='test list, use `,` interval')
F
v1.5.0  
frf12 已提交
1082
        self.parser.add_option('--exclude', type='string', help='exclude list, use `,` interval')
R
Rongfeng Fu 已提交
1083
        self.parser.add_option('--test-pattern', type='string', help='Pattern for test file.')
R
Rongfeng Fu 已提交
1084
        self.parser.add_option('--suite', type='string', help='Suite list. Multiple suites are separated with commas.')
R
Rongfeng Fu 已提交
1085
        self.parser.add_option('--suite-dir', type='string', help='Suite case directory. [./mysql_test/test_suite]', default='./mysql_test/test_suite')
F
v1.5.0  
frf12 已提交
1086
        self.parser.add_option('--init-sql-dir', type='string', help='Initiate sql directory. [./]', default='./')
R
Rongfeng Fu 已提交
1087
        self.parser.add_option('--init-sql-files', type='string', help='Initiate sql file list.Multiple files are separated with commas.')
R
Rongfeng Fu 已提交
1088
        self.parser.add_option('--need-init', action='store_true', help='Execute the init SQL file.', default=False)
F
v1.5.0  
frf12 已提交
1089
        self.parser.add_option('--init-only', action='store_true', help='Exit after executing init SQL.', default=False)
R
Rongfeng Fu 已提交
1090
        self.parser.add_option('--auto-retry', action='store_true', help='Auto retry when fails.', default=False)
F
v1.5.0  
frf12 已提交
1091
        self.parser.add_option('--all', action='store_true', help='Run all cases.', default=False)
R
Rongfeng Fu 已提交
1092
        self.parser.add_option('--psmall', action='store_true', help='Run psmall cases.', default=False)
F
v1.5.0  
frf12 已提交
1093 1094 1095
        self.parser.add_option('--special-run', action='store_true', help='run mysqltest in special mode.', default=False)
        self.parser.add_option('--sp-hint', type='string', help='run test with specified hint', default='')
        self.parser.add_option('--sort-result', action='store_true', help='sort query result', default=False)
O
oceanbase-admin 已提交
1096
        # self.parser.add_option('--java', action='store_true', help='use java sdk', default=False)
F
v1.5.0  
frf12 已提交
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
        self.parser.add_option('--slices', type='int', help='How many slices the test set should be')
        self.parser.add_option('--slice-idx', type='int', help='The id of slices')
        self.parser.add_option('--slb-host', type='string', help='The host of soft load balance.')
        self.parser.add_option('--exec-id', type='string', help='The unique execute id.')
        self.parser.add_option('--case-filter', type='string', help='The case filter file for mysqltest.')
        self.parser.add_option('--psmall-test', type='string', help='The file maintain psmall cases.', default='./mysql_test/psmalltest.py')
        self.parser.add_option('--psmall-source', type='string', help='The file maintain psmall source control.', default='./mysql_test/psmallsource.py')
        self.parser.add_option('--ps', action='store_true', help='Run in ps mode.', default=False)
        self.parser.add_option('--test-tags', type='string', help='The file maintain basic tags.', default='./mysql_test/test_tags.py')
        self.parser.add_option('--tags', type='string', help='Run cases by tag.', default='')
        self.parser.add_option('--regress-suite-map', type='string', help='The file maintain basic regress suite map', default='./regress_suite_map.py')
        self.parser.add_option('--regress_suite', type='string', help='Run cases by regress_suite.', default='')
        self.parser.add_option('--reboot-cases', type='string', help='The file maintain reboot cases')
        self.parser.add_option('--reboot-timeout', type='int', help='The timeout of observer bootstrap', default=0)
        self.parser.add_option('--reboot-retries', type='int', help='How many times to retry when rebooting failed', default=5)
        self.parser.add_option('--collect-all', action='store_true', help='Collect servers log.', default=False)
        self.parser.add_option('--collect-components', type='string', help='The components which need collect log, multiple components are separated with commas')
        self.parser.add_option('--case-timeout', type='int', help='The timeout of mysqltest case')
        self.parser.add_option('--log-pattern', type='string', help='The pattern for collected servers log ', default='*.log')
        self.parser.add_option('--cluster-mode', type='string', help="The mode of mysqltest")
        self.parser.add_option('--disable-reboot', action='store_true', help='Never reboot during test.', default=False)
F
v1.6.0  
frf12 已提交
1118
        self.parser.add_option('--fast-reboot', action='store_true', help='Reboot using snapshots.', default=False)
O
oceanbase-admin 已提交
1119 1120 1121 1122 1123 1124 1125 1126

    def _do_command(self, obd):
        if self.cmds:
            return obd.mysqltest(self.cmds[0], self.opts)
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
1127 1128 1129 1130
class SysBenchCommand(TestMirrorCommand):

    def __init__(self):
        super(SysBenchCommand, self).__init__('sysbench', 'Run sysbench for a deployment.')
R
Rongfeng Fu 已提交
1131 1132
        self.parser.add_option('--component', type='string', help='Components for test.')
        self.parser.add_option('--test-server', type='string', help='The server for test. By default, the first root server in the component is the test server.')
R
Rongfeng Fu 已提交
1133 1134
        self.parser.add_option('--user', type='string', help='Username for a test. [root]', default='root')
        self.parser.add_option('--password', type='string', help='Password for a test.')
F
v1.5.0  
frf12 已提交
1135
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
R
Rongfeng Fu 已提交
1136 1137 1138
        self.parser.add_option('--database', type='string', help='Database for a test. [test]', default='test')
        self.parser.add_option('--obclient-bin', type='string', help='OBClient bin path. [obclient]', default='obclient')
        self.parser.add_option('--sysbench-bin', type='string', help='Sysbench bin path. [sysbench]', default='sysbench')
R
Rongfeng Fu 已提交
1139
        self.parser.add_option('--script-name', type='string', help='Sysbench lua script file name. [oltp_point_select]', default='oltp_point_select.lua')
R
Rongfeng Fu 已提交
1140 1141 1142
        self.parser.add_option('--sysbench-script-dir', type='string', help='The directory of the sysbench lua script file. [/usr/sysbench/share/sysbench]', default='/usr/sysbench/share/sysbench')
        self.parser.add_option('--table-size', type='int', help='Number of data initialized per table. [20000]', default=20000)
        self.parser.add_option('--tables', type='int', help='Number of initialization tables. [30]', default=30)
F
v1.6.0  
frf12 已提交
1143
        self.parser.add_option('--threads', type='int', help='Number of threads to use. [16]', default=16)
R
Rongfeng Fu 已提交
1144 1145 1146 1147 1148
        self.parser.add_option('--time', type='int', help='Limit for total execution time in seconds. [60]', default=60)
        self.parser.add_option('--interval', type='int', help='Periodically report intermediate statistics with a specified time interval in seconds. 0 disables intermediate reports. [10]', default=10)
        self.parser.add_option('--events', type='int', help='Limit for total number of events.')
        self.parser.add_option('--rand-type', type='string', help='Random numbers distribution {uniform,gaussian,special,pareto}.')
        self.parser.add_option('--percentile', type='int', help='Percentile to calculate in latency statistics. Available values are 1-100. 0 means to disable percentile calculations.')
F
v1.6.0  
frf12 已提交
1149
        self.parser.add_option('--skip-trx', type='string', help='Open or close a transaction in a read-only test. {on/off}')
R
Rongfeng Fu 已提交
1150
        self.parser.add_option('-O', '--optimization', type='int', help='Optimization level {0/1/2}. [1] 0 - No optimization. 1 - Optimize some of the parameters which do not need to restart servers. 2 - Optimize all the parameters and maybe RESTART SERVERS for better performance.', default=1)
F
v1.6.0  
frf12 已提交
1151 1152
        self.parser.add_option('-S', '--skip-cluster-status-check', action='store_true', help='Skip cluster status check', default=False)
        self.parser.add_option('--mysql-ignore-errors', type='string', help='list of errors to ignore, or "all". ', default='1062')
R
Rongfeng Fu 已提交
1153 1154 1155 1156 1157 1158 1159 1160

    def _do_command(self, obd):
        if self.cmds:
            return obd.sysbench(self.cmds[0], self.opts)
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
1161 1162 1163 1164 1165 1166 1167 1168
class TPCHCommand(TestMirrorCommand):

    def __init__(self):
        super(TPCHCommand, self).__init__('tpch', 'Run a TPC-H test for a deployment.')
        self.parser.add_option('--component', type='string', help='Components for a test.')
        self.parser.add_option('--test-server', type='string', help='The server for a test. By default, the first root server in the component is the test server.')
        self.parser.add_option('--user', type='string', help='Username for a test. [root]', default='root')
        self.parser.add_option('--password', type='string', help='Password for a test.')
F
v1.5.0  
frf12 已提交
1169
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
R
Rongfeng Fu 已提交
1170 1171
        self.parser.add_option('--database', type='string', help='Database for a test. [test]', default='test')
        self.parser.add_option('--obclient-bin', type='string', help='OBClient bin path. [obclient]', default='obclient')
R
Rongfeng Fu 已提交
1172
        self.parser.add_option('--dbgen-bin', type='string', help='dbgen bin path. [/usr/tpc-h-tools/tpc-h-tools/bin/dbgen]', default='/usr/tpc-h-tools/tpc-h-tools/bin/dbgen')
R
Rongfeng Fu 已提交
1173 1174 1175 1176 1177 1178 1179
        self.parser.add_option('-s', '--scale-factor', type='int', help='Set Scale Factor (SF) to <n>. [1] ', default=1)
        self.parser.add_option('--tmp-dir', type='string', help='The temporary directory for executing TPC-H. [./tmp]', default='./tmp')
        self.parser.add_option('--ddl-path', type='string', help='Directory for DDL files.')
        self.parser.add_option('--tbl-path', type='string', help='Directory for tbl files.')
        self.parser.add_option('--sql-path', type='string', help='Directory for SQL files.')
        self.parser.add_option('--remote-tbl-dir', type='string', help='Directory for the tbl on target observers. Make sure that you have read and write access to the directory when you start observer.')
        self.parser.add_option('--disable-transfer', '--dt', action='store_true', help='Disable the transfer. When enabled, OBD will use the tbl files under remote-tbl-dir instead of transferring local tbl files to remote remote-tbl-dir.')
R
Rongfeng Fu 已提交
1180
        self.parser.add_option('--dss-config', type='string', help='Directory for dists.dss. [/usr/tpc-h-tools/tpc-h-tools]', default='/usr/tpc-h-tools/tpc-h-tools/')
R
Rongfeng Fu 已提交
1181
        self.parser.add_option('-O', '--optimization', type='int', help='Optimization level {0/1/2}. [1] 0 - No optimization. 1 - Optimize some of the parameters which do not need to restart servers. 2 - Optimize all the parameters and maybe RESTART SERVERS for better performance.', default=1)
R
Rongfeng Fu 已提交
1182
        self.parser.add_option('--test-only', action='store_true', help='Only testing SQLs are executed. No initialization is executed.')
F
v1.6.0  
frf12 已提交
1183
        self.parser.add_option('-S', '--skip-cluster-status-check', action='store_true', help='Skip cluster status check', default=False)
R
Rongfeng Fu 已提交
1184 1185 1186 1187 1188 1189 1190 1191

    def _do_command(self, obd):
        if self.cmds:
            return obd.tpch(self.cmds[0], self.opts)
        else:
            return self._show_help()


F
v1.6.0  
frf12 已提交
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
class TPCDSCommand(TestMirrorCommand):

    def __init__(self):
        super(TPCDSCommand, self).__init__('tpcds', 'Run a TPC-DS test for a deployment.')
        self.parser.add_option('--component', type='string', help='Components for a test.')
        self.parser.add_option('--test-server', type='string', help='The server for a test. By default, the first root server in the component is the test server.')
        self.parser.add_option('--user', type='string', help='Username for a test.')
        self.parser.add_option('--password', type='string', help='Password for a test.')
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
        self.parser.add_option('--mode', type='string', help='Tenant compatibility mode. {mysql,oracle} [mysql]', default='mysql')
        self.parser.add_option('--database', type='string', help='Database for a test. [test]', default='test')
        self.parser.add_option('--obclient-bin', type='string', help='OBClient bin path. [obclient]', default='obclient')
        self.parser.add_option('--tool-dir', type='string', help='tpc-ds tool dir. [/usr/tpc-ds-tools]')
        self.parser.add_option('--dsdgen-bin', type='string', help='dsdgen bin path. [$TOOL_DIR/bin/dsdgen]')
        self.parser.add_option('--idx-file', type='string', help='tpcds.idx file path. [$TOOL_DIR/bin/tpcds.idx]')
        self.parser.add_option('--dsqgen-bin', type='string', help='dsqgen bin path. [$TOOL_DIR/bin/dsqgen]')
        self.parser.add_option('--query-templates-dir', type='string', help='Query templates dir. [$TOOL_DIR/query_templates]')
        self.parser.add_option('-s', '--scale', type='int', help='Set Scale Factor (SF) to <n>. [1] ', default=1)
        self.parser.add_option('--disable-generate', '--dg', action='store_true', help='Do not generate test data.')
        self.parser.add_option('-p', '--generate-parallel', help='Generate data parallel number. [0]', default=0)
        self.parser.add_option('--tmp-dir', type='string', help='The temporary directory for executing TPC-H. [./tmp]', default='./tmp')
        self.parser.add_option('--ddl-path', type='string', help='Directory for DDL files.')
        self.parser.add_option('--sql-path', type='string', help='Directory for SQL files.')
        self.parser.add_option('--create-foreign-key', '--fk', action='store_true', help='create foreign key.')
        self.parser.add_option('--foreign-key-file', '--fk-file', action='store_true', help='SQL file for creating foreign key.')
        self.parser.add_option('--remote-dir', type='string', help='Directory for the data file on target observers. Make sure that you have read and write access to the directory when you start observer.')
        self.parser.add_option('--test-only', action='store_true', help='Only testing SQLs are executed. No initialization is executed.')

    def _do_command(self, obd):
        if self.cmds:
            return obd.tpcds(self.cmds[0], self.opts)
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
1227 1228 1229 1230 1231 1232 1233 1234
class TPCCCommand(TestMirrorCommand):

    def __init__(self):
        super(TPCCCommand, self).__init__('tpcc', 'Run a TPC-C test for a deployment.')
        self.parser.add_option('--component', type='string', help='Components for a test.')
        self.parser.add_option('--test-server', type='string', help='The server for a test. By default, the first root server in the component is the test server.')
        self.parser.add_option('--user', type='string', help='Username for a test. [root]', default='root')
        self.parser.add_option('--password', type='string', help='Password for a test.')
F
v1.5.0  
frf12 已提交
1235
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
R
Rongfeng Fu 已提交
1236 1237 1238 1239 1240 1241 1242 1243
        self.parser.add_option('--database', type='string', help='Database for a test. [test]', default='test')
        self.parser.add_option('--obclient-bin', type='string', help='OBClient bin path. [obclient]', default='obclient')
        self.parser.add_option('--java-bin', type='string', help='Java bin path. [java]', default='java')
        self.parser.add_option('--tmp-dir', type='string', help='The temporary directory for executing TPC-C. [./tmp]', default='./tmp')
        self.parser.add_option('--bmsql-dir', type='string', help='The directory of BenchmarkSQL.')
        self.parser.add_option('--bmsql-jar', type='string', help='BenchmarkSQL jar path.')
        self.parser.add_option('--bmsql-libs', type='string', help='BenchmarkSQL libs path.')
        self.parser.add_option('--bmsql-sql-dir', type='string', help='The directory of BenchmarkSQL sql scripts.')
F
v1.5.0  
frf12 已提交
1244
        self.parser.add_option('--warehouses', type='int', help='The number of warehouses.[10]', default=10)
R
Rongfeng Fu 已提交
1245 1246
        self.parser.add_option('--load-workers', type='int', help='The number of workers to load data.')
        self.parser.add_option('--terminals', type='int', help='The number of terminals.')
F
v1.5.0  
frf12 已提交
1247
        self.parser.add_option('--run-mins', type='int', help='To run for specified minutes.[10]', default=10)
R
Rongfeng Fu 已提交
1248 1249
        self.parser.add_option('--test-only', action='store_true', help='Only testing SQLs are executed. No initialization is executed.')
        self.parser.add_option('-O', '--optimization', type='int', help='Optimization level {0/1/2}. [1] 0 - No optimization. 1 - Optimize some of the parameters which do not need to restart servers. 2 - Optimize all the parameters and maybe RESTART SERVERS for better performance.', default=1)
F
v1.6.0  
frf12 已提交
1250
        self.parser.add_option('-S', '--skip-cluster-status-check', action='store_true', help='Skip cluster status check', default=False)
R
Rongfeng Fu 已提交
1251 1252 1253 1254 1255 1256

    def _do_command(self, obd):
        if self.cmds:
            return obd.tpcc(self.cmds[0], self.opts)
        else:
            return self._show_help()
F
v1.5.0  
frf12 已提交
1257

R
Rongfeng Fu 已提交
1258

O
oceanbase-admin 已提交
1259 1260 1261
class TestMajorCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1262
        super(TestMajorCommand, self).__init__('test', 'Run test for a running deployment.')
O
oceanbase-admin 已提交
1263
        self.register_command(MySQLTestCommand())
R
Rongfeng Fu 已提交
1264
        self.register_command(SysBenchCommand())
R
Rongfeng Fu 已提交
1265
        self.register_command(TPCHCommand())
F
v1.4.0  
frf12 已提交
1266
        self.register_command(TPCCCommand())
F
v1.6.0  
frf12 已提交
1267
        # self.register_command(TPCDSCommand())
O
oceanbase-admin 已提交
1268 1269


F
v1.5.0  
frf12 已提交
1270 1271 1272 1273 1274 1275
class DbConnectCommand(HiddenObdCommand):

    def init(self, cmd, args):
        super(DbConnectCommand, self).init(cmd, args)
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
        return self
R
Rongfeng Fu 已提交
1276 1277 1278 1279
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
F
v1.5.0  
frf12 已提交
1280 1281 1282 1283 1284 1285

    def __init__(self):
        super(DbConnectCommand, self).__init__('db_connect', 'Establish a database connection to the deployment.')
        self.parser.add_option('-c', '--component', type='string', help='The component used by database connection.')
        self.parser.add_option('-s', '--server', type='string',
                               help='The server used by database connection. The first server in the configuration will be used by default')
F
v1.6.0  
frf12 已提交
1286
        self.parser.add_option('-u', '--user', type='string', help='The username used by database connection. [root]', default='root')
F
v1.5.0  
frf12 已提交
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
        self.parser.add_option('-p', '--password', type='string', help='The password used by database connection.')
        self.parser.add_option('-t', '--tenant', type='string', help='The tenant used by database connection. [sys]', default='sys')
        self.parser.add_option('-D', '--database', type='string', help='The database name used by database connection.')
        self.parser.add_option('--obclient-bin', type='string', help='OBClient bin path. [obclient]', default='obclient')

    def _do_command(self, obd):
        if self.cmds:
            return obd.db_connect(self.cmds[0], self.opts)
        else:
            return self._show_help()


F
v1.6.0  
frf12 已提交
1299 1300 1301 1302 1303 1304
class DoobaCommand(HiddenObdCommand):

    def init(self, cmd, args):
        super(DoobaCommand, self).init(cmd, args)
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
        return self
R
Rongfeng Fu 已提交
1305 1306 1307 1308
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
F
v1.6.0  
frf12 已提交
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326

    def __init__(self):
        super(DoobaCommand, self).__init__('dooba', 'A curses powerful tool for OceanBase admin, more than a monitor')
        self.parser.add_option('-c', '--component', type='string', help='The component used by database connection.')
        self.parser.add_option('-s', '--server', type='string',
                               help='The server used by database connection. The first server in the configuration will be used by default')
        self.parser.add_option('-u', '--user', type='string', help='The username used by database connection. [root]',
                               default='root')
        self.parser.add_option('-p', '--password', type='string', help='The password used by database connection.')
        self.parser.add_option('--dooba-bin', type='string', help='Dooba bin path.')

    def _do_command(self, obd):
        if self.cmds:
            return obd.dooba(self.cmds[0], self.opts)
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
1327
class CommandsCommand(ObdCommand):
F
v1.5.0  
frf12 已提交
1328 1329 1330 1331 1332

    def init(self, cmd, args):
        super(CommandsCommand, self).init(cmd, args)
        self.parser.set_usage('%s <deploy name> <command> [options]' % self.prev_cmd)
        return self
R
Rongfeng Fu 已提交
1333 1334 1335 1336
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
F
v1.5.0  
frf12 已提交
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355

    def __init__(self):
        super(CommandsCommand, self).__init__('command', 'Common tool commands')
        self.parser.add_option('-c', '--components', type='string', help='The components used by the command. The first component in the configuration will be used by default in interactive commands, and all available components will be used by default in non-interactive commands.')
        self.parser.add_option('-s', '--servers', type='string', help='The servers used by the command. The first server in the configuration will be used by default in interactive commands, and all available servers will be used by default in non-interactive commands.')

    def _do_command(self, obd):
        if len(self.cmds) == 2:
            return obd.commands(self.cmds[0], self.cmds[1], self.opts)
        else:
            return self._show_help()


class ToolCommand(HiddenMajorCommand):

    def __init__(self):
        super(ToolCommand, self).__init__('tool', 'Tools')
        self.register_command(DbConnectCommand())
        self.register_command(CommandsCommand())
F
v1.6.0  
frf12 已提交
1356
        self.register_command(DoobaCommand())
F
v1.5.0  
frf12 已提交
1357 1358


O
oceanbase-admin 已提交
1359 1360 1361 1362 1363 1364
class BenchMajorCommand(MajorCommand):

    def __init__(self):
        super(BenchMajorCommand, self).__init__('bench', '')


R
Rongfeng Fu 已提交
1365 1366 1367
class UpdateCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1368
        super(UpdateCommand, self).__init__('update', 'Update OBD.')
R
Rongfeng Fu 已提交
1369 1370

    def do_command(self):
R
Rongfeng Fu 已提交
1371 1372 1373
        uid = os.getuid()
        if uid != 0 and not DirectoryUtil.get_owner(self.OBD_INSTALL_PRE):
            ROOT_IO.error('To update OBD, you must be the owner of %s.' % self.OBD_INSTALL_PRE)
R
Rongfeng Fu 已提交
1374 1375
            return False
        return super(UpdateCommand, self).do_command()
R
Rongfeng Fu 已提交
1376
    
R
Rongfeng Fu 已提交
1377
    def _do_command(self, obd):
R
Rongfeng Fu 已提交
1378
        return obd.update_obd(VERSION, self.OBD_INSTALL_PRE)
R
Rongfeng Fu 已提交
1379 1380


R
Rongfeng Fu 已提交
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
class DisplayTraceCommand(ObdCommand):

    def __init__(self):
        super(DisplayTraceCommand, self).__init__('display-trace', 'display trace_id log.')
        self.has_trace = False

    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

R
Rongfeng Fu 已提交
1391 1392 1393 1394
    @property
    def enable_log(self):
        return False

R
Rongfeng Fu 已提交
1395 1396
    def _do_command(self, obd):
        from ssh import LocalClient
R
Rongfeng Fu 已提交
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
        if not self.cmds:
            return self._show_help()
        log_dir = os.path.join(obd.home_path, 'log/obd')
        trace_id = self.cmds[0]
        ROOT_IO.verbose('Get log by trace_id')
        try:
            if UUID(trace_id).version != 1:
                ROOT_IO.critical('%s is not trace id' % trace_id)
                return False
        except:
            ROOT_IO.print('%s is not trace id' % trace_id)
            return False
        cmd = 'grep -h "\[{}\]" {}* | sed "s/\[{}\] //g" '.format(trace_id, log_dir, trace_id)
        data = LocalClient.execute_command(cmd)
        ROOT_IO.print(data.stdout)
        return True


class ObdiagCommand(MajorCommand):
    
    def __init__(self):
        super(ObdiagCommand, self).__init__('obdiag', 'Oceanbase Diagnostic Tool')
        self.register_command(ObdiagDeployCommand())
        self.register_command(ObdiagGatherCommand())


class ObdiagDeployCommand(ObdCommand):


    def __init__(self):
        super(ObdiagDeployCommand, self).__init__('deploy', 'deploy obdiag')
        self.parser.allow_undefine = True
        self.parser.undefine_warn = False

    def _do_command(self, obd):
        obd.set_options(self.opts)
        return obd.obdiag_deploy()


class ObdiagGatherMirrorCommand(ObdCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherMirrorCommand, self).init(cmd, args)
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
        return self

    def _do_command(self, obd):
R
Rongfeng Fu 已提交
1444
        if self.cmds:
R
Rongfeng Fu 已提交
1445
            return obd.obdiag_gather(self.cmds[0], "gather_%s" % self.name, self.opts)
R
Rongfeng Fu 已提交
1446
        else:
R
Rongfeng Fu 已提交
1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
            return self._show_help()


class ObdiagGatherCommand(MajorCommand):
    
    def __init__(self):
        super(ObdiagGatherCommand, self).__init__('gather', 'Gather oceanbase diagnostic info')
        self.register_command(ObdiagGatherAllCommand())
        self.register_command(ObdiagGatherLogCommand())
        self.register_command(ObdiagGatherSysStatCommand())
        self.register_command(ObdiagGatherStackCommand())
        self.register_command(ObdiagGatherPerfCommand())
        self.register_command(ObdiagGatherSlogCommand())
        self.register_command(ObdiagGatherClogCommand())
        self.register_command(ObdiagGatherPlanMonitorCommand())
        self.register_command(ObdiagGatherObproxyLogCommand())

class ObdiagGatherAllCommand(ObdiagGatherMirrorCommand):

    def init(self, cmd, args):
        super(ObdiagGatherAllCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherAllCommand, self).__init__('all', 'Gather oceanbase diagnostic info')
        self.parser.add_option('--from', type='string', help="specify the start of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--to', type='string', help="specify the end of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--since', type='string',  help="Specify time range that from 'n' [d]ays, 'n' [h]ours or 'n' [m]inutes. before to now. format: <n> <m|h|d>. example: 1h.",default='30m')
        self.parser.add_option('--scope', type='string', help="log type constrains, choices=[observer, election, rootservice, all]",default='all')
        self.parser.add_option('--grep', type='string', help="specify keywords constrain")
        self.parser.add_option('--encrypt', type='string', help="Whether the returned results need to be encrypted, choices=[true, false]", default="false")
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)

class ObdiagGatherLogCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherLogCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherLogCommand, self).__init__('log', 'Gather oceanbase logs from oceanbase machines')
        self.parser.add_option('--from', type='string', help="specify the start of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--to', type='string', help="specify the end of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--since', type='string',  help="Specify time range that from 'n' [d]ays, 'n' [h]ours or 'n' [m]inutes. before to now. format: <n> <m|h|d>. example: 1h.",default='30m')
        self.parser.add_option('--scope', type='string', help="log type constrains, choices=[observer, election, rootservice, all]",default='all')
        self.parser.add_option('--grep', type='string', help="specify keywords constrain")
        self.parser.add_option('--encrypt', type='string', help="Whether the returned results need to be encrypted, choices=[true, false]", default="false")
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherSysStatCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherSysStatCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherSysStatCommand, self).__init__('sysstat', 'Gather Host information')
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherStackCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherStackCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherStackCommand, self).__init__('stack', 'Gather stack')
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherPerfCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherPerfCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherPerfCommand, self).__init__('perf', 'Gather perf')
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--scope', type='string', help="perf type constrains, choices=[sample, flame, pstack, all]",default='all')
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherSlogCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherSlogCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherSlogCommand, self).__init__('slog', 'Gather slog')
        self.parser.add_option('--from', type='string', help="specify the start of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--to', type='string', help="specify the end of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--since', type='string',  help="Specify time range that from 'n' [d]ays, 'n' [h]ours or 'n' [m]inutes. before to now. format: <n> <m|h|d>. example: 1h.",default='30m')
        self.parser.add_option('--encrypt', type='string', help="Whether the returned results need to be encrypted, choices=[true, false]", default="false")
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherClogCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherClogCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherClogCommand, self).__init__('clog', 'Gather clog')
        self.parser.add_option('--from', type='string', help="specify the start of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--to', type='string', help="specify the end of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--since', type='string',  help="Specify time range that from 'n' [d]ays, 'n' [h]ours or 'n' [m]inutes. before to now. format: <n> <m|h|d>. example: 1h.",default='30m')
        self.parser.add_option('--encrypt', type='string', help="Whether the returned results need to be encrypted, choices=[true, false]", default="false")
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherPlanMonitorCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherPlanMonitorCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherPlanMonitorCommand, self).__init__('plan_monitor', 'Gather ParalleSQL information')
        self.parser.add_option('-c', '--component', type='string', help="Component name to connect.", default='oceanbase-ce')
        self.parser.add_option('--trace_id', type='string', help='sql trace id')
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('-u', '--user', type='string', help='The username used by database connection. [root]',default='root')
        self.parser.add_option('-p', '--password', type='string', help='The password used by database connection.',default='')
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)


class ObdiagGatherObproxyLogCommand(ObdiagGatherMirrorCommand):
    
    def init(self, cmd, args):
        super(ObdiagGatherObproxyLogCommand, self).init(cmd, args)
        return self
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK

    def __init__(self):
        super(ObdiagGatherObproxyLogCommand, self).__init__('obproxy_log', 'Gather obproxy log from obproxy machines')
        self.parser.add_option('--from', type='string', help="specify the start of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--to', type='string', help="specify the end of the time range. format: yyyy-mm-dd hh:mm:ss")
        self.parser.add_option('--since', type='string',  help="Specify time range that from 'n' [d]ays, 'n' [h]ours or 'n' [m]inutes. before to now. format: <n> <m|h|d>. example: 1h.",default='30m')
        self.parser.add_option('--scope', type='string', help="log type constrains, choices=[observer, election, rootservice, all]",default='all')
        self.parser.add_option('--grep', type='string', help="specify keywords constrain")
        self.parser.add_option('--encrypt', type='string', help="Whether the returned results need to be encrypted, choices=[true, false]", default="false")
        self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default=os.getcwd())
        self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH)
R
Rongfeng Fu 已提交
1636 1637


O
oceanbase-admin 已提交
1638 1639 1640 1641
class MainCommand(MajorCommand):

    def __init__(self):
        super(MainCommand, self).__init__('obd', '')
R
Rongfeng Fu 已提交
1642
        self.register_command(DevModeMajorCommand())
F
v1.6.0  
frf12 已提交
1643
        self.register_command(DemoCommand())
R
Rongfeng Fu 已提交
1644
        self.register_command(WebCommand())
O
oceanbase-admin 已提交
1645 1646
        self.register_command(MirrorMajorCommand())
        self.register_command(ClusterMajorCommand())
R
Rongfeng Fu 已提交
1647
        self.register_command(RepositoryMajorCommand())
O
oceanbase-admin 已提交
1648
        self.register_command(TestMajorCommand())
R
Rongfeng Fu 已提交
1649
        self.register_command(UpdateCommand())
R
Rongfeng Fu 已提交
1650
        self.register_command(DisplayTraceCommand())
F
v1.5.0  
frf12 已提交
1651
        self.register_command(EnvironmentMajorCommand())
R
Rongfeng Fu 已提交
1652
        self.register_command(TelemetryMajorCommand())
F
v1.5.0  
frf12 已提交
1653
        self.register_command(ToolCommand())
R
Rongfeng Fu 已提交
1654
        self.register_command(ObdiagCommand())
O
oceanbase-admin 已提交
1655
        self.parser.version = '''OceanBase Deploy: %s
R
Rongfeng Fu 已提交
1656 1657 1658
REVISION: %s
BUILD_BRANCH: %s
BUILD_TIME: %s
O
oceanbase-admin 已提交
1659 1660 1661
Copyright (C) 2021 OceanBase
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
R
Rongfeng Fu 已提交
1662
There is NO WARRANTY, to the extent permitted by law.''' % (VERSION, REVISION, BUILD_BRANCH, BUILD_TIME)
O
oceanbase-admin 已提交
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
        self.parser._add_version_option()

if __name__ == '__main__':
    defaultencoding = 'utf-8'
    if sys.getdefaultencoding() != defaultencoding:
        try:
            from imp import reload
        except:
            pass
        reload(sys)
        sys.setdefaultencoding(defaultencoding)
R
Rongfeng Fu 已提交
1674
    sys.path.append(os.path.join(ObdCommand.OBD_INSTALL_PATH, 'lib/site-packages'))
O
oceanbase-admin 已提交
1675 1676 1677 1678 1679
    ROOT_IO.track_limit += 2
    if MainCommand().init('obd', sys.argv[1:]).do_command():
        ROOT_IO.exit(0)
    ROOT_IO.exit(1)