Files
2024-05-31 10:51:25 +08:00

238 lines
7.5 KiB
Python

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
#############################################################################
# Copyright (c) 2023 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms
# and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# ----------------------------------------------------------------------------
# Description : gs_upgradechk is a utility to check meta data in gaussdb after upgrade.
#############################################################################
"""
参数模块
"""
import os
import sys
from getopt import getopt, GetoptError
from enum import Enum
from upgrade_checker.utils.exception import ParamParseException
class Action(Enum):
"""
程序运行动作
"""
HELP = 0
VERIFY = 1
EXPORT = 2
class ReportFormat(Enum):
"""
报告格式
"""
MARKDOWN = 0
@staticmethod
def suffix(fmt):
if fmt == ReportFormat.MARKDOWN:
return 'md'
else:
assert False
class ReportMode(Enum):
"""
报告粒度
"""
SUMMARY = 0
DETAIL = 1
class Option(object):
def __init__(self, value, shortopt, longopt, assign_func=None):
"""
一个参数选项
:param value: 默认值
:param shortopt: 解析时的短命令
:param longopt: 解析时的长命令
:param assign_func: 设置新值时的检查函数
:return:
"""
self.value = value
self.shortopt = shortopt
self.longopt = longopt
self.assign_func = assign_func
def assign(self, value):
self.value = value if self.assign_func is None else self.assign_func(value)
class Param(object):
helper = """
命令格式:
python3 main.py [action [params, ...] ]
参数 ACTION,所需执行的动作:
check | verify 校验数据库元数据
export 导出一份元数据地图
help | -h | -? 打印帮助
参数 params:
-p | --port 数据库端口
-F | --report_format 报告格式,支持markdown
-M | --report_mode 报告模式,detail详细,summary摘要,默认summary
-v | --vmap 指定使用某个地图,不然自己检测数据库版本并下载。默认自己检测
-d | --debug 开启debug运行模式,将会打印更多的日志。
-D | --database 对指定数据库进行导出或校验操作。
更多详细内容参考《README.md》
"""
def __init__(self, root_path, argv):
self._opt_info = ['', []] # shotopts, longopts
self._opt_dict = {}
self.root_path = root_path
self.action = Action.HELP
self.port = self._register(16666, 'p:', 'port=', Param.assign_port)
self.report_format = self._register(ReportFormat.MARKDOWN, 'F:', 'report-format=', Param.assign_report_format)
self.report_mode = self._register(ReportMode.SUMMARY, 'M:', 'report-mode=', Param.assign_report_mode)
self.vmap = self._register(None, 'v:', 'vmap=', Param.assign_vmap)
self.debug = self._register(False, 'd', 'debug', Param.assign_debug)
self.database = self._register(None, 'D:', 'database=', Param.assign_database)
try:
self._parse(argv[1:])
except ParamParseException as e:
self.action = Action.HELP
print('ERROR:', e)
def __str__(self):
return 'Param as: ' + str({
'root_path': self.root_path,
'action': self.action,
'port': self.port.value,
'report_format': self.report_format.value,
'report_mode': self.report_mode.value,
'vmap': self.vmap.value,
'debug': self.debug.value,
'database': self.database
}) + '\n'
def _register(self, value, shortopt, longopt, assign_func=None):
"""
创建并返回一个Option,同时将长短指令添加到_opt_info中,用以解析,将Option添加到自身字典内,以长短指令为键
:param value: 默认值
:param shortopt: 解析时的短命令
:param longopt: 解析时的长命令
:param assign_func: 设置新值时的检查函数
:return:
"""
opt = Option(value, shortopt, longopt, assign_func)
self._opt_info[0] += shortopt
self._opt_info[1].append(longopt)
short_key = '-' + (shortopt if shortopt[-1] != ':' else shortopt[:-1])
long_key = '--' + (longopt if longopt[-1] != '=' else longopt[:-1])
assert self._opt_dict.get(short_key) is None
assert self._opt_dict.get(long_key) is None
self._opt_dict[short_key] = opt
self._opt_dict[long_key] = opt
return opt
def _parse(self, argv):
"""
解析参数,第一个参数必须是action,后面的逐个解析
:param argv: 参数列表
:return:
"""
self.action = Param.assign_action(argv)
if self.is_help():
return
try:
opts, unused = getopt(argv[1:], self._opt_info[0], self._opt_info[1])
except GetoptError as e:
raise ParamParseException(e.msg)
if len(unused) > 0:
raise ParamParseException('解析出错,未知的参数{}'.format(unused[0]))
for key, value in opts:
opt = self._opt_dict.get(key)
assert opt is not None
opt.assign(value)
def is_help(self):
return self.action == Action.HELP
@staticmethod
def assign_action(argv):
if len(argv) == 0:
return Action.HELP
action = argv[0]
if action.lower() in ("help", "--help", "-h", "-?"):
return Action.HELP
elif action.lower() in ["check", "verify"]:
return Action.VERIFY
elif action.lower() == "export":
return Action.EXPORT
else:
raise ParamParseException("错误的动作参数'{0}'.".format(action))
@staticmethod
def assign_port(port):
port = int(port)
if 0 < port < 65535:
return port
else:
raise ParamParseException("错误的端口参数port {0}, 请保持在(0, 65535)".format(port))
@staticmethod
def assign_report_format(fmt):
if fmt.lower() in ['md', 'markdown']:
return ReportFormat.MARKDOWN
else:
raise ParamParseException("错误的格式参数report-format {0},当前仅支持markdown格式。".format(fmt))
@staticmethod
def assign_report_mode(gran):
if gran.lower() == 'summary':
return ReportMode.SUMMARY
elif gran.lower() == 'detail':
return ReportMode.DETAIL
else:
raise ParamParseException("错误的模式参数report-mode {0},仅支持summary、detail。".format(gran))
@staticmethod
def assign_vmap(vmap):
return os.path.abspath(vmap)
@staticmethod
def assign_debug(debug):
return True
@staticmethod
def assign_database(database):
return database
if __name__ == "__main__":
test_param = Param(sys.path[0], sys.argv)
print(test_param)