_cmd.py 66.0 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
from uuid import uuid1 as uuid, UUID
F
v1.6.0  
frf12 已提交
29
from optparse import OptionParser, OptionGroup, BadOptionError, Option, IndentedHelpFormatter
O
oceanbase-admin 已提交
30 31 32

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


ROOT_IO = IO(1)
F
v1.5.0  
frf12 已提交
40
VERSION = '<VERSION>'
R
Rongfeng Fu 已提交
41 42 43
REVISION = '<CID>'
BUILD_BRANCH = '<B_BRANCH>'
BUILD_TIME = '<B_TIME>'
O
oceanbase-admin 已提交
44

F
v1.5.0  
frf12 已提交
45 46
CONST_OBD_HOME = "OBD_HOME"
CONST_OBD_INSTALL_PRE = "OBD_INSTALL_PRE"
R
Rongfeng Fu 已提交
47 48
CONST_OBD_INSTALL_PATH = "OBD_INSTALL_PATH"
FORBIDDEN_VARS = (CONST_OBD_HOME, CONST_OBD_INSTALL_PRE, CONST_OBD_INSTALL_PATH)
F
v1.5.0  
frf12 已提交
49 50 51

OBD_HOME_PATH = os.path.join(os.environ.get(CONST_OBD_HOME, os.getenv('HOME')), '.obd')
COMMAND_ENV.load(os.path.join(OBD_HOME_PATH, '.obd_environ'), ROOT_IO)
F
v1.6.0  
frf12 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77


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 已提交
78

O
oceanbase-admin 已提交
79

R
Rongfeng Fu 已提交
80
class AllowUndefinedOptionParser(OptionParser):
F
v1.5.0  
frf12 已提交
81
    IS_TTY = sys.stdin.isatty()
R
Rongfeng Fu 已提交
82 83 84 85 86 87 88 89 90 91 92 93

    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 已提交
94 95 96
                allow_undefine=True,
                undefine_warn=True
        ):
R
Rongfeng Fu 已提交
97 98 99 100 101
        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 已提交
102
        self.undefine_warn = undefine_warn
R
Rongfeng Fu 已提交
103 104

    def warn(self, msg, file=None):
F
v1.5.0  
frf12 已提交
105 106 107 108
        if self.IS_TTY:
            print("%s %s" % (IO.WARNING_PREV, msg))
        else:
            print('warn: %s' % msg)
R
Rongfeng Fu 已提交
109 110 111

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

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


O
oceanbase-admin 已提交
137 138 139 140 141 142 143 144 145 146
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 已提交
147
        self.hidden = False
R
Rongfeng Fu 已提交
148
        self.has_trace = True
R
Rongfeng Fu 已提交
149
        self.parser = AllowUndefinedOptionParser(add_help_option=False)
R
Rongfeng Fu 已提交
150 151
        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 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

    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 已提交
180
        return self.parser.format_help(OptionHelpFormatter())
O
oceanbase-admin 已提交
181 182 183 184


class ObdCommand(BaseCommand):

F
v1.5.0  
frf12 已提交
185 186
    OBD_PATH = OBD_HOME_PATH
    OBD_INSTALL_PRE = os.environ.get(CONST_OBD_INSTALL_PRE, '/')
R
Rongfeng Fu 已提交
187
    OBD_INSTALL_PATH = os.environ.get(CONST_OBD_INSTALL_PATH, os.path.join(OBD_INSTALL_PRE, 'usr/obd/'))
O
oceanbase-admin 已提交
188 189 190 191 192 193

    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 已提交
194
        if VERSION != version:
F
v1.6.0  
frf12 已提交
195
            for part in ['plugins', 'config_parser', 'optimize', 'mirror/remote']:
R
Rongfeng Fu 已提交
196 197
                obd_part_dir = os.path.join(self.OBD_PATH, part)
                if DirectoryUtil.mkdir(self.OBD_PATH):
R
Rongfeng Fu 已提交
198
                    root_part_path = os.path.join(self.OBD_INSTALL_PATH, part)
R
Rongfeng Fu 已提交
199 200
                    if os.path.exists(root_part_path):
                        DirectoryUtil.copy(root_part_path, obd_part_dir, ROOT_IO)
O
oceanbase-admin 已提交
201 202 203 204 205 206
            version_fobj.seek(0)
            version_fobj.truncate()
            version_fobj.write(VERSION)
            version_fobj.flush()
        version_fobj.close()

R
Rongfeng Fu 已提交
207 208
    @property
    def dev_mode(self):
R
Rongfeng Fu 已提交
209 210 211 212 213
        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 已提交
214 215

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

O
oceanbase-admin 已提交
220 221 222
    def do_command(self):
        self.parse_command()
        self.init_home()
R
Rongfeng Fu 已提交
223 224
        trace_id = uuid()
        ret = False
O
oceanbase-admin 已提交
225 226 227 228
        try:
            log_dir = os.path.join(self.OBD_PATH, 'log')
            DirectoryUtil.mkdir(log_dir)
            log_path = os.path.join(log_dir, 'obd')
F
v1.6.0  
frf12 已提交
229
            ROOT_IO.init_trace_logger(log_path, 'obd', trace_id)
R
Rongfeng Fu 已提交
230
            obd = ObdHome(home_path=self.OBD_PATH, dev_mode=self.dev_mode, lock_mode=self.lock_mode, stdio=ROOT_IO)
O
oceanbase-admin 已提交
231
            ROOT_IO.track_limit += 1
R
Rongfeng Fu 已提交
232 233
            ROOT_IO.verbose('cmd: %s' % self.cmds)
            ROOT_IO.verbose('opts: %s' % self.opts)
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())


O
oceanbase-admin 已提交
422 423 424
class MirrorCloneCommand(ObdCommand):

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

    def init(self, cmd, args):
        super(MirrorCloneCommand, self).init(cmd, args)
R
Rongfeng Fu 已提交
430
        self.parser.set_usage('%s [mirror path] [options]' % self.prev_cmd)
O
oceanbase-admin 已提交
431 432 433 434 435
        return self

    def _do_command(self, obd):
        if self.cmds:
            for src in self.cmds:
R
Rongfeng Fu 已提交
436
                if not obd.add_mirror(src):
O
oceanbase-admin 已提交
437 438 439 440 441 442 443 444 445
                    return False
            return True
        else:
            return self._show_help()


class MirrorCreateCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
446
        super(MirrorCreateCommand, self).__init__('create', 'Create a local mirror by using the local binary file.')
O
oceanbase-admin 已提交
447
        self.parser.conflict_handler = 'resolve'
R
Rongfeng Fu 已提交
448 449 450 451 452
        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 已提交
453 454 455
        self.parser.conflict_handler = 'error'

    def _do_command(self, obd):
R
Rongfeng Fu 已提交
456
        return obd.create_repository()
O
oceanbase-admin 已提交
457 458 459 460 461


class MirrorListCommand(ObdCommand):

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

F
v1.6.0  
frf12 已提交
464 465 466 467 468
    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 已提交
469 470
    def show_pkg(self, name, pkgs):
        ROOT_IO.print_list(
R
Rongfeng Fu 已提交
471 472
            pkgs,
            ['name', 'version', 'release', 'arch', 'md5'],
O
oceanbase-admin 已提交
473 474 475 476 477 478 479 480 481 482 483 484
            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 已提交
485
                repos = obd.mirror_manager.get_mirrors(is_enabled=None)
O
oceanbase-admin 已提交
486
                for repo in repos:
R
Rongfeng Fu 已提交
487
                    if repo.section_name == name:
R
Rongfeng Fu 已提交
488 489 490
                        if not repo.enabled:
                            ROOT_IO.error('Mirror repository %s is disabled.' % name)
                            return False
O
oceanbase-admin 已提交
491 492 493 494 495 496
                        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 已提交
497
            repos = obd.mirror_manager.get_mirrors(is_enabled=None)
O
oceanbase-admin 已提交
498
            ROOT_IO.print_list(
R
Rongfeng Fu 已提交
499
                repos,
R
Rongfeng Fu 已提交
500 501
                ['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 已提交
502 503
                title='Mirror Repository List'
            )
F
v1.6.0  
frf12 已提交
504
            ROOT_IO.print("Use `obd mirror list <section name>` for more details")
O
oceanbase-admin 已提交
505 506 507 508 509 510
        return True


class MirrorUpdateCommand(ObdCommand):

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

O
oceanbase-admin 已提交
513 514
    def _do_command(self, obd):
        success = True
R
Rongfeng Fu 已提交
515 516 517
        current = int(time.time())
        mirrors = obd.mirror_manager.get_remote_mirrors()
        for mirror in mirrors:
O
oceanbase-admin 已提交
518
            try:
R
Rongfeng Fu 已提交
519 520
                if mirror.enabled and mirror.repo_age < current:
                    success = mirror.update_mirror() and success
O
oceanbase-admin 已提交
521 522 523
            except:
                success = False
                ROOT_IO.stop_loading('fail')
R
Rongfeng Fu 已提交
524
                ROOT_IO.exception('Fail to synchronize mirorr (%s)' % mirror.name)
O
oceanbase-admin 已提交
525 526 527
        return success


R
Rongfeng Fu 已提交
528 529 530 531
class MirrorEnableCommand(ObdCommand):

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

R
Rongfeng Fu 已提交
533
    def _do_command(self, obd):
R
Rongfeng Fu 已提交
534 535 536 537
        ret = True
        for name in self.cmds:
            ret = obd.mirror_manager.set_remote_mirror_enabled(name, True) and ret
        return ret
R
Rongfeng Fu 已提交
538 539 540 541 542 543


class MirrorDisableCommand(ObdCommand):

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

R
Rongfeng Fu 已提交
545
    def _do_command(self, obd):
R
Rongfeng Fu 已提交
546 547 548 549 550 551 552 553 554
        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 已提交
555

R
Rongfeng Fu 已提交
556 557 558 559
    def _do_command(self, obd):
        url = self.cmds[0]
        return obd.mirror_manager.add_repo(url)
        
R
Rongfeng Fu 已提交
560

O
oceanbase-admin 已提交
561 562 563
class MirrorMajorCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
564
        super(MirrorMajorCommand, self).__init__('mirror', 'Manage a component repository for OBD.')
O
oceanbase-admin 已提交
565 566 567 568
        self.register_command(MirrorListCommand())
        self.register_command(MirrorCloneCommand())
        self.register_command(MirrorCreateCommand())
        self.register_command(MirrorUpdateCommand())
R
Rongfeng Fu 已提交
569 570
        self.register_command(MirrorEnableCommand())
        self.register_command(MirrorDisableCommand())
R
Rongfeng Fu 已提交
571
        self.register_command(MirrorAddRepoCommand())
O
oceanbase-admin 已提交
572 573


R
Rongfeng Fu 已提交
574 575 576 577
class RepositoryListCommand(ObdCommand):

    def __init__(self):
        super(RepositoryListCommand, self).__init__('list', 'List local repository.')
R
Rongfeng Fu 已提交
578 579 580 581
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
R
Rongfeng Fu 已提交
582 583 584 585

    def show_repo(self, repos, name=None):
        ROOT_IO.print_list(
            repos,
R
Rongfeng Fu 已提交
586
            ['name', 'version', 'release', 'arch', 'md5', 'tags'],
R
Rongfeng Fu 已提交
587
            lambda x: [x.name, x.version, x.release, x.arch, x.md5, ', '.join(x.tags)],
F
v1.5.0  
frf12 已提交
588
            title='%s Local Repository List' % name if name else 'Local Repository List'
R
Rongfeng Fu 已提交
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
        )

    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 已提交
605 606 607 608
class ClusterMirrorCommand(ObdCommand):

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


R
Rongfeng Fu 已提交
613 614 615 616 617 618 619 620 621
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 已提交
622
            return obd.change_deploy_config_style(self.cmds[0])
R
Rongfeng Fu 已提交
623 624 625 626 627 628 629 630 631 632 633 634 635 636
        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 已提交
637
            return obd.check_for_ocp(self.cmds[0])
R
Rongfeng Fu 已提交
638 639 640 641
        else:
            return self._show_help()


F
v1.6.0  
frf12 已提交
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
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 已提交
657 658 659
        obd.set_options(self.opts)
        return obd.demo()

F
v1.6.0  
frf12 已提交
660

R
Rongfeng Fu 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
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 已提交
681

R
Rongfeng Fu 已提交
682 683 684 685 686 687
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 已提交
688 689
        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 已提交
690
        self.parser.add_option('-U', '--unuselibrepo', '--ulp', action='store_true', help="Disable OBD from installing the libs mirror automatically.")
A
Amber Zhang 已提交
691
        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 已提交
692 693 694 695 696
        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 已提交
697 698
            if getattr(self.opts, 'force', False) or getattr(self.opts, 'clean', False):
                setattr(self.opts, 'skip_cluster_status_check', True)
R
Rongfeng Fu 已提交
699
                obd.set_options(self.opts)
R
Rongfeng Fu 已提交
700
            name = self.cmds[0]
R
Rongfeng Fu 已提交
701
            if obd.genconfig(name):
R
Rongfeng Fu 已提交
702
                self.opts.config = ''
R
Rongfeng Fu 已提交
703 704 705
                obd.set_cmds(self.cmds[1:])
                return obd.deploy_cluster(name) and obd.start_cluster(name)
            return False
R
Rongfeng Fu 已提交
706 707 708 709
        else:
            return self._show_help()


O
oceanbase-admin 已提交
710 711 712
class ClusterDeployCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
713 714 715
        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 已提交
716
        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 已提交
717
        self.parser.add_option('-U', '--unuselibrepo', '--ulp', action='store_true', help="Disable OBD from installing the libs mirror automatically.")
A
Amber Zhang 已提交
718
        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 已提交
719 720 721 722
        # 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 已提交
723 724
            if getattr(self.opts, 'force', False) or getattr(self.opts, 'clean', False):
                setattr(self.opts, 'skip_cluster_status_check', True)
R
Rongfeng Fu 已提交
725 726
                obd.set_options(self.opts)
            return obd.deploy_cluster(self.cmds[0])
O
oceanbase-admin 已提交
727 728 729 730 731 732 733
        else:
            return self._show_help()


class ClusterStartCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
734
        super(ClusterStartCommand, self).__init__('start', 'Start a deployed cluster.')
R
Rongfeng Fu 已提交
735 736
        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 已提交
737 738
        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 已提交
739
        self.parser.add_option('--without-parameter', '--wop', action='store_true', help='Start without parameters.')
O
oceanbase-admin 已提交
740 741 742

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
743 744
            obd.set_cmds(self.cmds[1:])
            return obd.start_cluster(self.cmds[0])
O
oceanbase-admin 已提交
745 746 747 748 749 750 751
        else:
            return self._show_help()


class ClusterStopCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
752
        super(ClusterStopCommand, self).__init__('stop', 'Stop a started cluster.')
R
Rongfeng Fu 已提交
753 754
        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 已提交
755 756 757

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
758
            return obd.stop_cluster(self.cmds[0])
O
oceanbase-admin 已提交
759 760 761 762 763 764 765
        else:
            return self._show_help()


class ClusterDestroyCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
766 767
        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 已提交
768 769 770

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
771
            return obd.destroy_cluster(self.cmds[0])
O
oceanbase-admin 已提交
772 773 774 775 776 777 778
        else:
            return self._show_help()


class ClusterDisplayCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
779
        super(ClusterDisplayCommand, self).__init__('display', 'Display the information for a cluster.')
O
oceanbase-admin 已提交
780 781 782 783 784 785 786 787 788 789 790

    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 已提交
791
        super(ClusterRestartCommand, self).__init__('restart', 'Restart a started cluster.')
R
Rongfeng Fu 已提交
792 793
        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 已提交
794
        self.parser.add_option('--with-parameter', '--wp', action='store_true', help='Restart with parameters.')
O
oceanbase-admin 已提交
795 796 797

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
798 799
            if not getattr(self.opts, 'with_parameter', False):
                setattr(self.opts, 'without_parameter', True)
R
Rongfeng Fu 已提交
800 801
            obd.set_options(self.opts)
            return obd.restart_cluster(self.cmds[0])
O
oceanbase-admin 已提交
802 803 804 805 806 807 808
        else:
            return self._show_help()


class ClusterRedeployCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
809 810
        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 已提交
811 812 813

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


class ClusterReloadCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
822
        super(ClusterReloadCommand, self).__init__('reload', 'Reload a started cluster.')
O
oceanbase-admin 已提交
823 824 825 826 827 828 829 830 831 832 833

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


class ClusterListCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
834
        super(ClusterListCommand, self).__init__('list', 'List all the deployments.')
R
Rongfeng Fu 已提交
835 836 837 838
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
O
oceanbase-admin 已提交
839 840 841 842 843 844 845 846 847 848 849

    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 已提交
850
        super(ClusterEditConfigCommand, self).__init__('edit-config', 'Edit the configuration file for a specific deployment.')
O
oceanbase-admin 已提交
851 852 853 854 855 856 857 858

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


R
Rongfeng Fu 已提交
859 860 861
class ClusterChangeRepositoryCommand(ClusterMirrorCommand):

    def __init__(self):
F
v1.5.0  
frf12 已提交
862
        super(ClusterChangeRepositoryCommand, self).__init__('reinstall', 'Reinstall a deployed component')
R
Rongfeng Fu 已提交
863 864 865 866 867 868
        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 已提交
869
            return obd.reinstall(self.cmds[0])
R
Rongfeng Fu 已提交
870 871 872 873
        else:
            return self._show_help()


R
Rongfeng Fu 已提交
874 875 876
class CLusterUpgradeCommand(ClusterMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
877
        super(CLusterUpgradeCommand, self).__init__('upgrade', 'Upgrade a cluster.')
R
Rongfeng Fu 已提交
878 879 880 881 882
        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 已提交
883
        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 已提交
884 885 886

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
887
            return obd.upgrade_cluster(self.cmds[0])
R
Rongfeng Fu 已提交
888 889 890
        else:
            return self._show_help()

R
Rongfeng Fu 已提交
891 892 893 894 895

class ClusterTenantCreateCommand(ClusterMirrorCommand):

    def __init__(self):
        super(ClusterTenantCreateCommand, self).__init__('create', 'Create a tenant.')
F
v1.5.0  
frf12 已提交
896
        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 已提交
897 898
        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 已提交
899 900 901 902 903 904
        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 已提交
905
        self.parser.add_option('--min-iops', type='int', help="Min IOPS unit number.")
F
v1.5.0  
frf12 已提交
906 907
        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 已提交
908 909
        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 已提交
910
        self.parser.add_option('--mode', type='string', help='Tenant compatibility mode. {mysql,oracle} [mysql]', default='mysql')
R
Rongfeng Fu 已提交
911 912
        self.parser.add_option('--charset', type='string', help="Tenant charset.")
        self.parser.add_option('--collate', type='string', help="Tenant COLLATE.")
R
Rongfeng Fu 已提交
913
        self.parser.add_option('--replica-num', type='int', help="Tenant replica number.")
R
Rongfeng Fu 已提交
914 915
        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 已提交
916
        self.parser.add_option('--primary-zone', type='string', help="Tenant primary zone. [RANDOM].", default='RANDOM')
R
Rongfeng Fu 已提交
917
        self.parser.add_option('--locality', type='string', help="Tenant locality.")
R
Rongfeng Fu 已提交
918
        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 已提交
919 920 921

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
922
            return obd.create_tenant(self.cmds[0])
R
Rongfeng Fu 已提交
923 924 925 926 927 928 929 930
        else:
            return self._show_help()


class ClusterTenantDropCommand(ClusterMirrorCommand):

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

    def _do_command(self, obd):
        if self.cmds:
R
Rongfeng Fu 已提交
935 936 937 938 939 940 941 942 943 944 945 946 947
            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 已提交
948 949 950 951 952 953 954
        else:
            return self._show_help()


class ClusterTenantCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
955
        super(ClusterTenantCommand, self).__init__('tenant', 'Create, drop or list a tenant.')
R
Rongfeng Fu 已提交
956 957
        self.register_command(ClusterTenantCreateCommand())
        self.register_command(ClusterTenantDropCommand())
R
Rongfeng Fu 已提交
958
        self.register_command(ClusterTenantListCommand())
R
Rongfeng Fu 已提交
959 960


O
oceanbase-admin 已提交
961 962 963
class ClusterMajorCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
964
        super(ClusterMajorCommand, self).__init__('cluster', 'Deploy and manage a cluster.')
R
Rongfeng Fu 已提交
965 966
        self.register_command(ClusterCheckForOCPChange())
        self.register_command(ClusterConfigStyleChange())
R
Rongfeng Fu 已提交
967
        self.register_command(ClusterAutoDeployCommand())
O
oceanbase-admin 已提交
968 969 970 971 972 973 974 975 976 977
        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 已提交
978
        self.register_command(CLusterUpgradeCommand())
R
Rongfeng Fu 已提交
979
        self.register_command(ClusterChangeRepositoryCommand())
R
Rongfeng Fu 已提交
980
        self.register_command(ClusterTenantCommand())
O
oceanbase-admin 已提交
981 982 983 984 985 986


class TestMirrorCommand(ObdCommand):

    def init(self, cmd, args):
        super(TestMirrorCommand, self).init(cmd, args)
R
Rongfeng Fu 已提交
987
        self.parser.set_usage('%s <deploy name> [options]' % self.prev_cmd)
O
oceanbase-admin 已提交
988 989 990 991 992 993
        return self


class MySQLTestCommand(TestMirrorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
994
        super(MySQLTestCommand, self).__init__('mysqltest', 'Run a mysqltest for a deployment.')
R
Rongfeng Fu 已提交
995 996
        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 已提交
997
        self.parser.add_option('--component', type='string', help='Components for mysqltest.')
R
Rongfeng Fu 已提交
998 999 1000 1001 1002 1003 1004
        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 已提交
1005
        self.parser.add_option('--test-file-suffix', type='string', help='Test case file suffix. [.test]', default='.test')
R
Rongfeng Fu 已提交
1006
        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 已提交
1007
        self.parser.add_option('--result-file-suffix', type='string', help='Result file suffix. [.result]', default='.result')
F
v1.4.0  
frf12 已提交
1008
        self.parser.add_option('--record', action='store_true', help='record mysqltest execution results', default=False)
F
v1.5.0  
frf12 已提交
1009 1010 1011
        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 已提交
1012 1013
        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 已提交
1014
        self.parser.add_option('--test-set', type='string', help='test list, use `,` interval')
F
v1.5.0  
frf12 已提交
1015
        self.parser.add_option('--exclude', type='string', help='exclude list, use `,` interval')
R
Rongfeng Fu 已提交
1016
        self.parser.add_option('--test-pattern', type='string', help='Pattern for test file.')
R
Rongfeng Fu 已提交
1017
        self.parser.add_option('--suite', type='string', help='Suite list. Multiple suites are separated with commas.')
R
Rongfeng Fu 已提交
1018
        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 已提交
1019
        self.parser.add_option('--init-sql-dir', type='string', help='Initiate sql directory. [./]', default='./')
R
Rongfeng Fu 已提交
1020
        self.parser.add_option('--init-sql-files', type='string', help='Initiate sql file list.Multiple files are separated with commas.')
R
Rongfeng Fu 已提交
1021
        self.parser.add_option('--need-init', action='store_true', help='Execute the init SQL file.', default=False)
F
v1.5.0  
frf12 已提交
1022
        self.parser.add_option('--init-only', action='store_true', help='Exit after executing init SQL.', default=False)
R
Rongfeng Fu 已提交
1023
        self.parser.add_option('--auto-retry', action='store_true', help='Auto retry when fails.', default=False)
F
v1.5.0  
frf12 已提交
1024
        self.parser.add_option('--all', action='store_true', help='Run all cases.', default=False)
R
Rongfeng Fu 已提交
1025
        self.parser.add_option('--psmall', action='store_true', help='Run psmall cases.', default=False)
F
v1.5.0  
frf12 已提交
1026 1027 1028
        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 已提交
1029
        # self.parser.add_option('--java', action='store_true', help='use java sdk', default=False)
F
v1.5.0  
frf12 已提交
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
        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 已提交
1051
        self.parser.add_option('--fast-reboot', action='store_true', help='Reboot using snapshots.', default=False)
O
oceanbase-admin 已提交
1052 1053 1054 1055 1056 1057 1058 1059

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


R
Rongfeng Fu 已提交
1060 1061 1062 1063
class SysBenchCommand(TestMirrorCommand):

    def __init__(self):
        super(SysBenchCommand, self).__init__('sysbench', 'Run sysbench for a deployment.')
R
Rongfeng Fu 已提交
1064 1065
        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 已提交
1066 1067
        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 已提交
1068
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
R
Rongfeng Fu 已提交
1069 1070 1071
        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 已提交
1072
        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 已提交
1073 1074 1075
        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 已提交
1076
        self.parser.add_option('--threads', type='int', help='Number of threads to use. [16]', default=16)
R
Rongfeng Fu 已提交
1077 1078 1079 1080 1081
        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 已提交
1082
        self.parser.add_option('--skip-trx', type='string', help='Open or close a transaction in a read-only test. {on/off}')
R
Rongfeng Fu 已提交
1083
        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 已提交
1084 1085
        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 已提交
1086 1087 1088 1089 1090 1091 1092 1093

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


R
Rongfeng Fu 已提交
1094 1095 1096 1097 1098 1099 1100 1101
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 已提交
1102
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
R
Rongfeng Fu 已提交
1103 1104
        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 已提交
1105
        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 已提交
1106 1107 1108 1109 1110 1111 1112
        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 已提交
1113
        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 已提交
1114
        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 已提交
1115
        self.parser.add_option('--test-only', action='store_true', help='Only testing SQLs are executed. No initialization is executed.')
F
v1.6.0  
frf12 已提交
1116
        self.parser.add_option('-S', '--skip-cluster-status-check', action='store_true', help='Skip cluster status check', default=False)
R
Rongfeng Fu 已提交
1117 1118 1119 1120 1121 1122 1123 1124

    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 已提交
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
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 已提交
1160 1161 1162 1163 1164 1165 1166 1167
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 已提交
1168
        self.parser.add_option('-t', '--tenant', type='string', help='Tenant for a test. [test]', default='test')
R
Rongfeng Fu 已提交
1169 1170 1171 1172 1173 1174 1175 1176
        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 已提交
1177
        self.parser.add_option('--warehouses', type='int', help='The number of warehouses.[10]', default=10)
R
Rongfeng Fu 已提交
1178 1179
        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 已提交
1180
        self.parser.add_option('--run-mins', type='int', help='To run for specified minutes.[10]', default=10)
R
Rongfeng Fu 已提交
1181 1182
        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 已提交
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

    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 已提交
1190

R
Rongfeng Fu 已提交
1191

O
oceanbase-admin 已提交
1192 1193 1194
class TestMajorCommand(MajorCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1195
        super(TestMajorCommand, self).__init__('test', 'Run test for a running deployment.')
O
oceanbase-admin 已提交
1196
        self.register_command(MySQLTestCommand())
R
Rongfeng Fu 已提交
1197
        self.register_command(SysBenchCommand())
R
Rongfeng Fu 已提交
1198
        self.register_command(TPCHCommand())
F
v1.4.0  
frf12 已提交
1199
        self.register_command(TPCCCommand())
F
v1.6.0  
frf12 已提交
1200
        # self.register_command(TPCDSCommand())
O
oceanbase-admin 已提交
1201 1202


F
v1.5.0  
frf12 已提交
1203 1204 1205 1206 1207 1208
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 已提交
1209 1210 1211 1212
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
F
v1.5.0  
frf12 已提交
1213 1214 1215 1216 1217 1218

    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 已提交
1219
        self.parser.add_option('-u', '--user', type='string', help='The username used by database connection. [root]', default='root')
F
v1.5.0  
frf12 已提交
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
        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 已提交
1232 1233 1234 1235 1236 1237
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 已提交
1238 1239 1240 1241
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
F
v1.6.0  
frf12 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259

    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 已提交
1260
class CommandsCommand(ObdCommand):
F
v1.5.0  
frf12 已提交
1261 1262 1263 1264 1265

    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 已提交
1266 1267 1268 1269
    
    @property
    def lock_mode(self):
        return LockMode.NO_LOCK
F
v1.5.0  
frf12 已提交
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288

    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 已提交
1289
        self.register_command(DoobaCommand())
F
v1.5.0  
frf12 已提交
1290 1291


O
oceanbase-admin 已提交
1292 1293 1294 1295 1296 1297
class BenchMajorCommand(MajorCommand):

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


R
Rongfeng Fu 已提交
1298 1299 1300
class UpdateCommand(ObdCommand):

    def __init__(self):
R
Rongfeng Fu 已提交
1301
        super(UpdateCommand, self).__init__('update', 'Update OBD.')
R
Rongfeng Fu 已提交
1302 1303

    def do_command(self):
R
Rongfeng Fu 已提交
1304 1305 1306
        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 已提交
1307 1308
            return False
        return super(UpdateCommand, self).do_command()
R
Rongfeng Fu 已提交
1309
    
R
Rongfeng Fu 已提交
1310
    def _do_command(self, obd):
R
Rongfeng Fu 已提交
1311
        return obd.update_obd(VERSION, self.OBD_INSTALL_PRE)
R
Rongfeng Fu 已提交
1312 1313


R
Rongfeng Fu 已提交
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
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

    def _do_command(self, obd):
        from ssh import LocalClient
        if self.cmds:
            if obd.stdio.log_path:
                log_dir = obd.stdio.log_path
                obd.stdio = IO(0, 20)
                trace_id = self.cmds[0]
                obd._call_stdio('verbose', 'Get log by trace_id')
                try:
                    if UUID(trace_id).version != 1:
                        obd._call_stdio('critical', '%s is not trace id' % trace_id)
                        return False
                except:
                    obd._call_stdio('critical', '%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)
                obd.stdio.print(data.stdout)
                return True
        else:
            self._show_help()
        return False


O
oceanbase-admin 已提交
1348 1349 1350 1351
class MainCommand(MajorCommand):

    def __init__(self):
        super(MainCommand, self).__init__('obd', '')
R
Rongfeng Fu 已提交
1352
        self.register_command(DevModeMajorCommand())
F
v1.6.0  
frf12 已提交
1353
        self.register_command(DemoCommand())
R
Rongfeng Fu 已提交
1354
        self.register_command(WebCommand())
O
oceanbase-admin 已提交
1355 1356
        self.register_command(MirrorMajorCommand())
        self.register_command(ClusterMajorCommand())
R
Rongfeng Fu 已提交
1357
        self.register_command(RepositoryMajorCommand())
O
oceanbase-admin 已提交
1358
        self.register_command(TestMajorCommand())
R
Rongfeng Fu 已提交
1359
        self.register_command(UpdateCommand())
R
Rongfeng Fu 已提交
1360
        self.register_command(DisplayTraceCommand())
F
v1.5.0  
frf12 已提交
1361 1362
        self.register_command(EnvironmentMajorCommand())
        self.register_command(ToolCommand())
O
oceanbase-admin 已提交
1363
        self.parser.version = '''OceanBase Deploy: %s
R
Rongfeng Fu 已提交
1364 1365 1366
REVISION: %s
BUILD_BRANCH: %s
BUILD_TIME: %s
O
oceanbase-admin 已提交
1367 1368 1369
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 已提交
1370
There is NO WARRANTY, to the extent permitted by law.''' % (VERSION, REVISION, BUILD_BRANCH, BUILD_TIME)
O
oceanbase-admin 已提交
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
        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 已提交
1382
    sys.path.append(os.path.join(ObdCommand.OBD_INSTALL_PATH, 'lib/site-packages'))
O
oceanbase-admin 已提交
1383 1384 1385 1386 1387
    ROOT_IO.track_limit += 2
    if MainCommand().init('obd', sys.argv[1:]).do_command():
        ROOT_IO.exit(0)
    ROOT_IO.exit(1)