From 9172daec18b140a01d3a32d7b77829a84a0cf44f Mon Sep 17 00:00:00 2001 From: NilCent Date: Thu, 28 Nov 2024 15:12:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E6=97=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E6=97=B6=E9=97=B4=E6=A0=A1=E9=AA=8C=E5=8F=8A?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E6=A0=A1=E9=AA=8C=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/base_diff/comm_constants.py | 2 + .../domain_utils/cluster_file/version_info.py | 84 +++++++++++++++++++ script/gs_upgradectl | 3 + script/gspylib/common/ErrorCode.py | 6 +- script/impl/upgrade/UpgradeImpl.py | 16 +++- 5 files changed, 106 insertions(+), 5 deletions(-) diff --git a/script/base_diff/comm_constants.py b/script/base_diff/comm_constants.py index e6084f3..9de9eab 100644 --- a/script/base_diff/comm_constants.py +++ b/script/base_diff/comm_constants.py @@ -23,6 +23,8 @@ class CommConstants: VERSION_PATTERN = r'(\d+\.\d+\.\d+)(-RC\d+)?' VERSION_EXAMPLE = "openGauss-1.0" + RELEASE_DATE_PATTERN = r'\d{4}-\d{2}-\d{2}' + PKG_SERVER = "Server" PKG_OM = "OM" PKG_CM = "CM" diff --git a/script/domain_utils/cluster_file/version_info.py b/script/domain_utils/cluster_file/version_info.py index a4ab0fa..cfd4e0d 100644 --- a/script/domain_utils/cluster_file/version_info.py +++ b/script/domain_utils/cluster_file/version_info.py @@ -135,6 +135,90 @@ class VersionInfo(object): + " Commit id is wrong.") return version, number, commit_id + @staticmethod + def get_release_date_from_app(app): + """ + function: get the infomation of gaussdb release date + :param: gaussdb absolute path + :return: gaussdb release date + """ + if not os.path.exists(app): + raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % app) + if not os.path.isfile(app): + raise Exception(ErrorCode.GAUSS_502["GAUSS_50210"] % app) + cmd = app + " -V" + (status, output) = subprocess.getstatusoutput(cmd) + if status != 0: + raise Exception(ErrorCode.GAUSS_501["GAUSS_50110"] % cmd) + + release_date = re.compile(CommConstants.RELEASE_DATE_PATTERN).search(output) + if release_date is None: + raise Exception(ErrorCode.GAUSS_501["GAUSS_50110"] % cmd) + + return release_date.group() + @staticmethod + def get_release_date(): + """ + function: Get release date from compressed pack + input : NA + output: String + """ + def _parse_pkg_prefix(_cfg): + _cmd = f'cat {_cfg}' + _status, _output = subprocess.getstatusoutput(_cmd) + if _status != 0: + raise Exception(ErrorCode.GAUSS_502["GAUSS_50217"] % + "version.cfg" + "The cmd is %s. " % _cmd + + "The output is %s." % _output) + _lines = _output.splitlines() + return _lines[0] + # obtain gaussdb + root = os.path.join(os.path.dirname(os.path.realpath(__file__)), './../../../') + version_file = os.path.join(root, 'version.cfg') + if not os.path.exists(version_file): + raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % version_file) + if not os.path.isfile(version_file): + raise Exception(ErrorCode.GAUSS_502["GAUSS_50210"] % version_file) + + pkg_prefix = _parse_pkg_prefix(version_file) + # upack and read version.cfg of openGauss-server package + # the existing om version.cfg will be overwritten + cmd = 'cd {} && tar -xpf {}*.tar.bz2 ./bin/gaussdb'.format(root, pkg_prefix) + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + cmd = 'cd {} && tar -xpf `ls openGauss-Server*.tar.bz2 | tail -1` ./bin/gaussdb'.format(root) + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + raise Exception(ErrorCode.GAUSS_502["GAUSS_50217"] % "bin/gaussdb" + + "The cmd is %s. " % cmd + + "The output is %s." % output) + + gaussdb_file = os.path.join(root, 'bin/gaussdb') + release_date = VersionInfo.get_release_date_from_app(gaussdb_file) + + cmd = 'cd {} && rm bin/gaussdb'.format(root) + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + raise Exception(ErrorCode.GAUSS_502["GAUSS_50217"] % "bin/gaussdb" + + "The cmd is %s. " % cmd + + "The output is %s." % output) + return release_date + + @staticmethod + def cmp_cluster_version(version1, version2): + v1_parts = list(map(int, version1.split('.'))) + v2_parts = list(map(int, version2.split('.'))) + + if len(v1_parts) != 3 or len(v2_parts) != 3: + raise Exception(ErrorCode.GAUSS_529["GAUSS_52946"]) + + for v1, v2 in zip(v1_parts, v2_parts): + if v1 < v2: + return -1 + elif v1 > v2: + return 1 + return 0 + @staticmethod def getAppVersion(appPath=""): """ diff --git a/script/gs_upgradectl b/script/gs_upgradectl index 88b6265..7f50241 100644 --- a/script/gs_upgradectl +++ b/script/gs_upgradectl @@ -146,6 +146,7 @@ General options: -l Path of log file. --force Force to rollback when cluster status is not normal + --bypass-stale-check allows upgrading from later releases to earlier releases --grey Use grey-binary-upgrade --upgrade-package Path of the CM component package --inplace-upgrade Use inplace-upgrade. @@ -187,6 +188,8 @@ Option for grey upgrade print("We no longer support force rollback. and '--force' is no longer in effect.") if "upgrade-package" in ParaDict.keys(): self.upgrade_package = ParaDict.get("upgrade-package") + if "bypass-stale-check" in ParaDict.keys: + self.bypass_stale_check = True self.tmpDir = EnvUtil.getTmpDirFromEnv() if self.tmpDir == "": raise Exception(ErrorCode.GAUSS_518["GAUSS_51800"] % "$PGHOST") diff --git a/script/gspylib/common/ErrorCode.py b/script/gspylib/common/ErrorCode.py index 3c1a425..60c7796 100644 --- a/script/gspylib/common/ErrorCode.py +++ b/script/gspylib/common/ErrorCode.py @@ -946,8 +946,10 @@ class ErrorCode(): 'GAUSS_52941': "[GAUSS-52941] : Invalid node role:%s.", 'GAUSS_52942': "[GAUSS-52942] : No such key to check guc value.", 'GAUSS_52943': "[GAUSS-52943] : Invalid instance type:%s.", - 'GAUSS_52944': "[GAUSS-52944] : Not all nodes are upgraded." - + 'GAUSS_52944': "[GAUSS-52944] : Not all nodes are upgraded.", + 'GAUSS_52945': "[GAUSS-52945] : It is generally not allowed to upgrade to a previous release, from %s to %s. " + "If required, consider using the --bypass-stale-check option.", + 'GAUSS_92946': "[GAUSS-52946] : Illegal cluster version." } ########################################################################### diff --git a/script/impl/upgrade/UpgradeImpl.py b/script/impl/upgrade/UpgradeImpl.py index 2aebe8d..67adfcf 100644 --- a/script/impl/upgrade/UpgradeImpl.py +++ b/script/impl/upgrade/UpgradeImpl.py @@ -530,6 +530,7 @@ class UpgradeImpl: newVersionFile = VersionInfo.get_version_file() newClusterVersion, newClusterNumber, newCommitId = \ VersionInfo.get_version_info(newVersionFile) + newReleaseDate = VersionInfo.get_release_date() gaussHome = ClusterDir.getInstallDir(self.context.user) if gaussHome == "": raise Exception(ErrorCode.GAUSS_518["GAUSS_51800"] @@ -563,6 +564,8 @@ class UpgradeImpl: self.context.logger.debug("Successfully obtained version" " information of old clusters by %s." % oldVersionFile) + oldAppFile = "%s/bin/gaussdb" % oldPath + oldReleaseDate = VersionInfo.get_release_date_from_app(oldAppFile) except Exception as e: if os.path.exists(self.context.upgradeBackupPath): # if upgradeBackupPath exist, @@ -576,6 +579,8 @@ class UpgradeImpl: % possibOldVersionFile) (oldClusterVersion, oldClusterNumber, oldCommitId) = \ VersionInfo.get_version_info(possibOldVersionFile) + possibAppFile = "%s/bin/gaussdb" % self.context.upgradeBackupPath + oldReleaseDate = VersionInfo.get_release_date_from_app(possibAppFile) else: raise Exception(str(e)) @@ -591,16 +596,21 @@ class UpgradeImpl: self.canDoRollbackOrCommit() - if oldClusterVersion > newClusterVersion: + if VersionInfo.cmp_cluster_version(oldClusterVersion, newClusterVersion) > 0: raise Exception(ErrorCode.GAUSS_529["GAUSS_52902"] % (oldClusterVersion, newClusterVersion)) - + self.checkLastUpgrade(newCommitId) if float(newClusterNumber) < float(oldClusterNumber): raise Exception(ErrorCode.GAUSS_516["GAUSS_51629"] % newClusterNumber) - elif float(newClusterNumber) == float(oldClusterNumber): + + if not self.context.bypass_stale_check and oldReleaseDate > newReleaseDate: + raise Exception(ErrorCode.GAUSS_529["GAUSS_52945"] + % (oldReleaseDate, newReleaseDate)) + + if float(newClusterNumber) == float(oldClusterNumber): if self.context.is_inplace_upgrade: upgradeAction = const.ACTION_INPLACE_UPGRADE else: -- Gitee