* Copyright (c) 2021 Huawei Technologies Co.,Ltd.
*
* CM 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.
* -------------------------------------------------------------------------
*
* ctl_pause.cpp
* cm_ctl pause
*
*
* IDENTIFICATION
* src/cm_ctl/ctl_pause.cpp
*
* -------------------------------------------------------------------------
*/
#include <signal.h>
#include "common/config/cm_config.h"
#include "cm/libpq-fe.h"
#include "cm/cm_misc.h"
#include "ctl_common.h"
#include "cm/cm_msg.h"
#include "cm/libpq-int.h"
#include "cm_ddb_adapter.h"
#include "ctl_common_res.h"
static status_t PauseCluster();
extern char manual_pause_file[MAXPGPATH];
extern char hosts_path[MAXPGPATH];
extern char pssh_out_path[MAXPGPATH];
extern bool got_stop;
extern char* g_command_operation_azName;
extern uint32 g_commandOperationNodeId;
static bool IsUpgradeCluster()
{
char upgradeCheck[MAX_PATH_LEN] = {0};
char pgHostPath[MAX_PATH_LEN] = {0};
int rcs = cm_getenv("PGHOST", pgHostPath, sizeof(pgHostPath));
if (rcs != EOK) {
write_runlog(ERROR, "get PGHOST failed!\n");
return false;
}
rcs = snprintf_s(upgradeCheck, MAX_PATH_LEN, MAX_PATH_LEN - 1, "%s/binary_upgrade", pgHostPath);
securec_check_intval(rcs, (void)rcs);
if (access(upgradeCheck, F_OK) == 0) {
write_runlog(DEBUG1, "Get upgrade file success.\n");
return true;
}
return false;
}
bool CheckTrustAndNet()
{
write_runlog(LOG, "Checking trust among all nodes.\n");
char command[MAXPGPATH] = {0};
int ret = snprintf_s(command, MAXPGPATH, MAXPGPATH - 1,
SYSTEMQUOTE "source /etc/profile;pssh -i -t 10 -h %s "
"\"pwd > /dev/null\" > /dev/null;" SYSTEMQUOTE, hosts_path);
securec_check_intval(ret, (void)ret);
write_runlog(DEBUG1, "Check trust command: %s\n", command);
ret = system(command);
if (ret != 0) {
return false;
}
return true;
}
int DoPause()
{
if (IsUpgradeCluster()) {
write_runlog(WARNING, "The cluster is upgrading currently. "
"Performing the pause operation is dangerous, because this may "
"cause upgrade failure.\nAre you sure want to continue? (y/[n])");
char yOrN = 'n';
yOrN = getchar();
if (yOrN != 'y') {
return CM_SUCCESS;
}
}
if (g_command_operation_azName != NULL || g_commandOperationNodeId != 0) {
write_runlog(ERROR, "Currently, this operation can only "
"be performed on the entire cluster.\n");
return CM_ERROR;
}
init_hosts();
if (!CheckTrustAndNet()) {
write_runlog(ERROR, "The ssh trust relationship may be abnormal on some nodes.\n");
return CM_ERROR;
}
status_t ret = PauseCluster();
(void)unlink(hosts_path);
return ret;
}
static status_t PauseCluster()
{
if (got_stop) {
return CM_SUCCESS;
}
write_runlog(LOG, "Pausing the cluster.\n");
char command[MAXPGPATH] = {0};
int ret = 0;
ret = snprintf_s(command, MAXPGPATH, MAXPGPATH - 1,
SYSTEMQUOTE "source /etc/profile;pssh -i %s -h %s \"touch %s\" > %s; "
"if [ $? -ne 0 ]; then cat %s; fi; rm -f %s" SYSTEMQUOTE,
PSSH_TIMEOUT_OPTION, hosts_path, manual_pause_file, pssh_out_path,
pssh_out_path, pssh_out_path);
securec_check_intval(ret, (void)ret);
ret = system(command);
if (ret != 0) {
write_runlog(ERROR,
"Failed to pause the cluster with executing the command: command=\"%s\","
" nodeId=%u, systemReturn=%d, shellReturn=%d, errno=%d.\n",
command, g_currentNode->node, ret, SHELL_RETURN_CODE(ret), errno);
return CM_ERROR;
}
write_runlog(LOG, "The cluster has been paused.\n");
return CM_SUCCESS;
}