* 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_ctl.cpp
* cm_ctl main files
*
* IDENTIFICATION
* src/cm_ctl/ctl_ctl.cpp
*
* -------------------------------------------------------------------------
*/
#include <fcntl.h>
#include "postgres_fe.h"
#include "cm/libpq-fe.h"
#include "cm/libpq-int.h"
#include "cm/pqsignal.h"
#include <arpa/inet.h>
#include <unordered_map>
#include "getopt_long.h"
#include "securec.h"
#include "common/config/cm_config.h"
#include "cm/cm_agent/cma_main.h"
#include "cm/cm_misc.h"
#include "cm_ddb_adapter.h"
#include "hotpatch/hotpatch_client.h"
#include "ctl_common.h"
#include "ctl_global_params.h"
#include "config.h"
#include "cm_util.h"
#include "ctl_help.h"
#include <string>
#include <vector>
#define ETCD_NUM_UPPER_LIMIT 50
#define CLUSTER_MANUAL_START "cluster_manual_start"
#define INSTANCE_MANUAL_START "instance_manual_start"
#define ETCD_MANUAL_START "etcd_manual_start"
#define MINORITY_AZ_START "minority_az_start"
#define MINORITY_AZ_ARBITRATE "minority_az_arbitrate_hist"
#define RESUMING_CN_STOP "resuming_cn_stop"
#define CLUSTER_MANUAL_PAUSE "cluster_manual_pause"
#define CLUSTER_MANUAL_STARTING "cluster_manual_starting"
#define CLUSTER_MANUAL_WALRECORD "cluster_manual_walrecord"
char* g_bin_name = NULL;
char* g_bin_path = NULL;
extern char sys_log_path[MAXPGPATH];
extern const char* prefix_name;
extern volatile int log_min_messages;
static bool lc_operation = false;
bool got_stop = false;
bool g_detailQuery = false;
bool g_formatQuery = false;
bool g_coupleQuery = false;
bool backup_process_query = false;
bool g_balanceQuery = false;
bool g_startStatusQuery = false;
bool g_abnormalQuery = false;
bool g_portQuery = false;
bool g_paralleRedoState = false;
bool g_dataPathQuery = false;
bool g_ipQuery = false;
bool g_availabilityZoneCommand = false;
bool switchover_all_quick = false;
bool g_kickStatQuery = false;
bool g_wormUsageQuery = false;
int do_force = 0;
int g_fencedUdfQuery = 0;
int shutdown_level = 0;
extern bool g_logFileSet;
bool g_nodeIdSet = false;
char g_cmdLine[MAX_PATH_LEN] = {0};
ShutdownMode shutdown_mode_num = FAST_MODE;
bool wait_seconds_set = false;
int g_waitSeconds = DEFAULT_WAIT;
CtlCommand ctl_command = NO_COMMAND;
uint32 g_normal_cm_server_node_index = PG_UINT32_MAX;
time_t CHECK_BUILDING_DN_TIMEOUT = 60;
bool is_check_building_dn = true;
char g_appPath[MAXPGPATH] = {0};
const char* g_progname;
static char* pgdata_opt = NULL;
char* g_logFile = NULL;
char* log_level_set = NULL;
bool log_level_get = false;
char* cm_arbitration_mode_set = NULL;
bool cm_arbitration_mode_get = false;
char* cm_switchover_az_mode_set = NULL;
bool cm_switchover_az_mode_get = false;
char* cm_logic_cluster_restart_mode_set = NULL;
char *g_dcfXMode = NULL;
int g_dcfVoteNum = 0;
char *g_cmsPromoteMode = NULL;
bool g_gtmBalance = true;
bool g_datanodesBalance = true;
int g_wormUsage = -1;
cm_to_ctl_central_node_status g_centralNode;
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
static char* hotpatch_exec = NULL;
static char* hotpatch_path = NULL;
#endif
char manual_start_file[MAXPGPATH];
char instance_manual_start_file[MAXPGPATH];
char cluster_manual_starting_file[MAXPGPATH];
char etcd_manual_start_file[MAXPGPATH];
static bool coordinator_dynamic_view = false;
#ifndef ENABLE_MULTIPLE_NODES
const char* g_ltranManualStart = "ltran_manual_start";
const char* g_libnetManualStart = "libnet_manual_start";
char g_ltranManualStartFile[MAXPGPATH];
char g_libnetManualStartFile[MAXPGPATH];
#else
#include "ctl_distribute.h"
bool cn_resumes_restart = false;
char resuming_cn_stop_file[MAX_PATH_LEN];
#endif
char cluster_static_config[MAXPGPATH];
static char cluster_dynamic_config[MAXPGPATH];
static char cm_server_bin[MAXPGPATH];
static char g_logicClusterListPath[MAX_PATH_LEN];
char minority_az_start_file[MAX_PATH_LEN];
char g_minorityAzArbitrateFile[MAX_PATH_LEN];
char manual_pause_file[MAXPGPATH];
char manual_walrecord_file[MAXPGPATH];
uint32 g_nodeId = 0;
uint32 g_commandOperationNodeId = 0;
uint32 g_commandOperationInstanceId = 0;
char* g_command_operation_lcName = NULL;
char* g_command_operation_azName = NULL;
char* g_commandMinortityAzName = NULL;
uint32 g_nodeIndexForCmServer[CM_PRIMARY_STANDBY_NUM] = {INVALID_NODE_NUM,
INVALID_NODE_NUM,
INVALID_NODE_NUM,
INVALID_NODE_NUM,
INVALID_NODE_NUM,
INVALID_NODE_NUM,
INVALID_NODE_NUM,
INVALID_NODE_NUM};
const char* g_cmServerState[CM_PRIMARY_STANDBY_NUM + 1] = {
"Init", "Init", "Init", "Init", "Init", "Init", "Init", "Init", "Init"};
static bool g_execute_cmctl_success = false;
char result_path[MAXPGPATH] = {0};
char hosts_path[MAXPGPATH] = {0};
char pssh_out_path[MAXPGPATH] = {0};
char g_cmData[CM_PATH_LENGTH] = {0};
bool g_commandRelationship = false;
bool g_isSharedStorageMode = false;
passwd* pw = NULL;
char mpp_env_separate_file[MAXPGPATH] = {0};
const int DCF_XMODE = 5;
const int DCF_VOTE_NUM = 6;
const int DCF_ROLE_MODE = 7;
const int MINORITY_AZ = 8;
const int CMS_P_MODE = 9;
const int CM_AGENT_MODE = 10;
const int CM_SERVER_MODE = 11;
const int CM_SWITCH_DDB = 12;
const int CM_SWITCH_COMMIT = 13;
const int CM_SWITCH_ROLLBACK = 14;
const int CM_SET_PARAM = 15;
const int DCF_GROUP = 16;
const int DCF_PRIORITY = 17;
const int RES_ADD = 18;
const int RES_EDIT = 19;
const int RES_DEL = 20;
const int RES_CHECK = 21;
const int RES_NAME_INPUT = 22;
const int RES_ATTR_INPUT = 23;
const int RES_ADD_INST_INPUT = 24;
const int RES_DEL_INST_INPUT = 25;
const int RES_EDIT_INST_INPUT = 27;
const int RES_INST_ATTR_INPUT = 28;
const int RES_LIST = 29;
const int RES_LIST_INST_INPUT = 30;
const int ErrorCode = -2;
static const char* g_allowedOptions = "aAb:B:cCD:dE:fFgil:I:j:k:L:m:M:n:NP:OpqrRsSt:T:uvwxz:";
static const vector<vector<int>> g_allowedActionOptions = {
{},
{ 'L' },
{ 'z', 'n', 'D', 'R', 'I', 'm', 't', 2 },
{ 'z', 'n', 'D', 'I', 'R', 't', 'm' },
{ 'z', 'n', 'D', 'q', 'f', 'a', 'A', 't' },
{'c', 'n', 'D', 't', 'f', 'b', 'j'},
{},
{'z', 'n', 'D', 'R', 'l', 'v', 'w', 'C', 's', 'S', 'd', 'i', 'F',
'L', 'x', 'p', 'r', 't', 'g', 'O', 'u', MINORITY_AZ},
{'I', 'n', 'k', 1, 2, 3, CMS_P_MODE, CM_SET_PARAM, CM_AGENT_MODE, CM_SERVER_MODE},
{1, 2, 3},
{},
{},
{},
{'v', 'n', 'N', 'c', 'l'},
{'B', 'T'},
{},
{'E', 'P'},
{'n', 'D', 't'},
{},
{'n', 'D', DCF_XMODE, DCF_VOTE_NUM},
{'n', 'D', 't', DCF_ROLE_MODE},
{'n', 'D', 't', DCF_ROLE_MODE, DCF_GROUP, DCF_PRIORITY},
{'n', CM_SET_PARAM, CM_AGENT_MODE, CM_SERVER_MODE},
{'n', CM_SET_PARAM, CM_AGENT_MODE, CM_SERVER_MODE},
{'M', 'D'},
{CM_SWITCH_DDB, CM_SWITCH_COMMIT, CM_SWITCH_ROLLBACK},
{RES_ADD, RES_NAME_INPUT, RES_ATTR_INPUT, RES_DEL, RES_EDIT, RES_LIST, RES_ADD_INST_INPUT, RES_DEL_INST_INPUT,
RES_EDIT_INST_INPUT, RES_INST_ATTR_INPUT, RES_LIST_INST_INPUT, RES_CHECK},
{},
{},
{},
{}
};
unordered_map<string, CtlCommand> g_optToCommand {
#ifdef ENABLE_MULTIPLE_NODES
{"restart", RESTART_COMMAND},
{"disable", CM_DISABLE_COMMAND},
#endif
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
{"hotpatch", CM_HOTPATCH_COMMAND},
#endif
{"set", CM_SET_COMMAND},
{"get", CM_GET_COMMAND},
{"view", CM_VIEW_COMMAND},
{"stop", STOP_COMMAND},
{"list", CM_LIST_COMMAND},
{"start", START_COMMAND},
{"build", CM_BUILD_COMMAND},
{"query", CM_QUERY_COMMAND},
{"check", CM_CHECK_COMMAND},
{"reload", CM_RELOAD_COMMAND},
{"switch", CM_SWITCH_COMMAND},
{"encrypt", CM_ENCRYPT_COMMAND},
{"setmode", CM_SETMODE_COMMAND},
#ifdef ENABLE_LIBPQ
{"finishredo", CM_FINISHREDO_COMMAND},
{"setrunmode", CM_DCF_SETRUNMODE_COMMAND},
{"changerole", CM_DCF_CHANGEROLE_COMMAND},
{"changemember", CM_DCF_CHANGEMEMBER_COMMAND},
#endif
{"switchover", CM_SWITCHOVER_COMMAND},
{"res", CM_RES_COMMAND},
{"show", CM_SHOW_COMMAND},
{"pause", CM_PAUSE_COMMAND},
{"resume", CM_RESUME_COMMAND},
{"rack", CM_RACK_COMMAND}
};
static string CheckActionOptions(CtlCommand ctlCommandAction, vector<int> optionIn, option* longActionOptions, int lengthLong)
{
string notMatched;
vector<int> checkInterOptions = g_allowedActionOptions[ctlCommandAction];
option optionInter;
int optionInLength = (int) optionIn.size();
for (int checkIndexO = 0; checkIndexO < optionInLength; ++checkIndexO) {
bool checkInArr = false;
int checkIndexI = 0;
while (checkIndexI < (int)checkInterOptions.size() && checkInterOptions[checkIndexI]!= 0) {
if (optionIn[checkIndexO] == checkInterOptions[checkIndexI]) {
checkInArr = true;
break;
}
++checkIndexI;
}
if (!checkInArr) {
if (!notMatched.empty()) {
notMatched.append(",");
}
if (optionIn[checkIndexO] <= RES_LIST_INST_INPUT) {
int checkInter = 0;
while (checkInter < lengthLong) {
optionInter = longActionOptions[checkInter];
if (optionIn[checkIndexO] == optionInter.val) {
notMatched.append(optionInter.name);
break;
}
++checkInter;
}
} else {
notMatched.push_back(char(optionIn[checkIndexO]));
}
}
}
return notMatched;
}
static status_t CheckActionOptionMatches(CtlCommand ctlCommandAction, vector<int> optionIn, option* longActionOptions, int lengthLong)
{
if (ctlCommandAction == NO_COMMAND) {
write_runlog2(FATAL, errcode(ERRCODE_READ_FILE_FAILURE),
errmsg("option requires an argument, NO_COMMAND only support 'V' and 'h'."));
DoAdvice();
return CM_ERROR;
}
string checkUnmatchedOption = CheckActionOptions(ctlCommandAction, optionIn, longActionOptions, lengthLong);
if (!checkUnmatchedOption.empty()) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("Commands and options do not match.\n"),
errmodule(MOD_CMCTL),
errcause("%s: The cmdline and options entered by the user is incorrect.\n", g_progname),
erraction("These options \"%s\" are not incorrect or not matched with the command.",
checkUnmatchedOption.c_str()));
DoAdvice();
return CM_ERROR;
}
return CM_SUCCESS;
}
static void InitializeCmServerNodeIndex(void)
{
uint32 i = 0;
for (uint32 curIndex = 0; curIndex < g_node_num; ++curIndex) {
if (g_node[curIndex].cmServerLevel != 1) {
continue;
}
g_nodeIndexForCmServer[i++] = curIndex;
}
}
uint32 *GetCmsNodeIndex()
{
return g_nodeIndexForCmServer;
}
* read cluster static config and init global parameters
*/
static int read_config_file_check()
{
int err_no = 0;
if (access(cluster_static_config, F_OK) != 0) {
write_runlog2(ERROR, errcode(ERRCODE_OPEN_FILE_FAILURE),
errmsg("Fail to access the cluster static config file."),
errdetail("The cluster static config file does not exist."), errmodule(MOD_CMCTL),
errcause("The cluster static config file is not generated or is manually deleted."),
erraction("Please check the cluster static config file."));
return 1;
}
int status = read_config_file(cluster_static_config, &err_no);
char errBuffer[ERROR_LIMIT_LEN] = {0};
switch (status) {
case OPEN_FILE_ERROR: {
write_runlog2(ERROR, errcode(ERRCODE_OPEN_FILE_FAILURE), errmsg("Fail to open the cluster static file."),
errdetail("[errno %d] %s.", err_no, strerror_r(err_no, errBuffer, ERROR_LIMIT_LEN)),
errmodule(MOD_CMCTL),
errcause("The cluster static config file is not generated or is manually deleted."),
erraction("Please check the cluster static config file."));
return 1;
}
case READ_FILE_ERROR: {
write_runlog2(ERROR, errcode(ERRCODE_READ_FILE_FAILURE), errmsg("Fail to read the cluster static file."),
errdetail("[errno %d] %s.\n", err_no, strerror_r(err_no, errBuffer, ERROR_LIMIT_LEN)),
errmodule(MOD_CMCTL), errcause("The cluster static file permission is insufficient."),
erraction("Please check the cluster static config file."));
return 1;
}
case OUT_OF_MEMORY:
write_runlog2(ERROR, errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to read the static config file."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("out of memeory."),
erraction("Please check the system memory and try again."));
return 1;
default:
break;
}
uint32 node_index = get_node_index(g_nodeHeader.node);
if (node_index >= g_node_num) {
write_runlog2(ERROR, errcode(ERRCODE_CONFIG_FILE_FAILURE),
errmsg("Could not find the current node in the cluster by the node id %u.", g_nodeHeader.node),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("The static config file probably contained content error."),
erraction("Please check static config file."));
return 1;
}
g_nodeId = node_index;
g_currentNode = &g_node[node_index];
InitializeCmServerNodeIndex();
if (lc_operation && access(g_logicClusterListPath, F_OK) == 0) {
status = read_logic_cluster_config_files(g_logicClusterListPath, &err_no);
char errBuff[ERROR_LIMIT_LEN] = {0};
switch (status) {
case OPEN_FILE_ERROR: {
write_runlog2(ERROR, errcode(ERRCODE_OPEN_FILE_FAILURE),
errmsg("Failed to open the logic config file."),
errdetail("[errno %d] %s", err_no, strerror_r(err_no, errBuff, ERROR_LIMIT_LEN)),
errmodule(MOD_CMCTL), errcause("The logic config file is not generated or is manually deleted."),
erraction("Please check the cluster static config file."));
return 1;
}
case READ_FILE_ERROR: {
write_runlog2(ERROR, errcode(ERRCODE_READ_FILE_FAILURE),
errmsg("Fail to read the logic static config file."),
errdetail("[errno %d] %s", err_no, strerror_r(err_no, errBuff, ERROR_LIMIT_LEN)),
errmodule(MOD_CMCTL), errcause("The logic static config file permission is insufficient."),
erraction("Please check the logic static config file."));
return 1;
}
case OUT_OF_MEMORY:
write_runlog2(ERROR,
errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to open or read the static config file."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("out of memeory."),
erraction("Please check the system memory and try again."));
return 1;
default:
break;
}
}
return 0;
}
static bool SetOutputFile(bool logFileSet, const char* logFile)
{
char errBuffer[ERROR_LIMIT_LEN];
if (logFileSet) {
g_logFilePtr = fopen(logFile, "w");
if (g_logFilePtr == NULL) {
if (errno == ENOENT) {
write_runlog(ERROR, "log file not found.\n");
return false;
} else {
write_runlog(ERROR,
"could not open log file \"%s\": %s\n",
logFile,
strerror_r(errno, errBuffer, ERROR_LIMIT_LEN));
return false;
}
}
} else {
g_logFilePtr = stdout;
}
return true;
}
static void RecordCommonInfo()
{
(void)fprintf(g_logFilePtr, "NodeHeader:\n");
(void)fprintf(g_logFilePtr, "version:%u\n", g_nodeHeader.version);
(void)fprintf(g_logFilePtr, "time:%ld\n", g_nodeHeader.time);
(void)fprintf(g_logFilePtr, "nodeCount:%u\n", g_nodeHeader.nodeCount);
(void)fprintf(g_logFilePtr, "node:%u\n", g_nodeHeader.node);
}
static void RecordNodeInfo(uint32 nodeId)
{
if (g_multi_az_cluster) {
(void)fprintf(g_logFilePtr, "azName:%s\n", g_node[nodeId].azName);
(void)fprintf(g_logFilePtr, "azPriority:%u\n", g_node[nodeId].azPriority);
}
(void)fprintf(g_logFilePtr, "node :%u\n", g_node[nodeId].node);
(void)fprintf(g_logFilePtr, "nodeName:%s\n", g_node[nodeId].nodeName);
(void)fprintf(g_logFilePtr, "ssh channel :\n");
for (uint32 jj = 0; jj < g_node[nodeId].sshCount; jj++) {
(void)fprintf(g_logFilePtr, "sshChannel %u:%s\n", jj + 1, g_node[nodeId].sshChannel[jj]);
}
}
static void RecordCmsInfo(uint32 nodeId)
{
if (g_node[nodeId].cmServerLevel != 1) {
return;
}
if (g_detailQuery || g_nodeIdSet) {
(void)fprintf(g_logFilePtr, "cmseverInstanceID :%u\n", g_node[nodeId].cmServerId);
}
(void)fprintf(g_logFilePtr, "cmDataPath :%s\n", g_node[nodeId].cmDataPath);
for (uint32 i = 0; i < g_node[nodeId].cmServerListenCount; i++) {
(void)fprintf(g_logFilePtr, "cmServer %u:%s\n", i + 1, g_node[nodeId].cmServer[i]);
}
(void)fprintf(g_logFilePtr, "port :%u\n", g_node[nodeId].port);
for (uint32 i = 0; i < g_node[nodeId].cmServerLocalHAListenCount; i++) {
(void)fprintf(g_logFilePtr, "cmServerLocalHAIP %u:%s\n", i + 1, g_node[nodeId].cmServerLocalHAIP[i]);
}
(void)fprintf(g_logFilePtr, "cmServerLocalHAPort :%u\n", g_node[nodeId].cmServerLocalHAPort);
for (uint32 i = 0; i < g_node[nodeId].cmServerPeerHAListenCount; i++) {
(void)fprintf(g_logFilePtr, "cmServerPeerHAIP %u:%s\n", i + 1, g_node[nodeId].cmServerPeerHAIP[i]);
}
(void)fprintf(g_logFilePtr, "cmServerPeerHAPort :%u\n", g_node[nodeId].cmServerPeerHAPort);
}
static void RecordCmaInfo(uint32 nodeId)
{
for (uint32 i = 0; i < g_node[nodeId].cmAgentListenCount; i++) {
(void)fprintf(g_logFilePtr, "cmAgentIP :%s\n", g_node[nodeId].cmAgentIP[i]);
}
}
static void RecordDnInfo(uint32 nodeId)
{
if (g_node[nodeId].datanodeCount == 0) {
return;
}
(void)fprintf(g_logFilePtr, "datanodeCount :%u\n", g_node[nodeId].datanodeCount);
for (uint32 kk = 0; kk < g_node[nodeId].datanodeCount; kk++) {
(void)fprintf(g_logFilePtr, "datanode %u:\n", kk + 1);
if (g_detailQuery || g_nodeIdSet) {
(void)fprintf(g_logFilePtr, "datanodeInstanceID :%u\n", g_node[nodeId].datanode[kk].datanodeId);
}
(void)fprintf(g_logFilePtr, "datanodeLocalDataPath :%s\n", g_node[nodeId].datanode[kk].datanodeLocalDataPath);
(void)fprintf(g_logFilePtr, "datanodeXlogPath :%s\n", g_node[nodeId].datanode[kk].datanodeXlogPath);
for (uint32 tt = 0; tt < g_node[nodeId].datanode[kk].datanodeListenCount; tt++) {
(void)fprintf(g_logFilePtr, "datanodeListenIP %u:%s\n",
tt + 1, g_node[nodeId].datanode[kk].datanodeListenIP[tt]);
}
(void)fprintf(g_logFilePtr, "datanodePort :%u\n", g_node[nodeId].datanode[kk].datanodePort);
for (uint32 tt = 0; tt < g_node[nodeId].datanode[kk].datanodeLocalHAListenCount; tt++) {
(void)fprintf(
g_logFilePtr, "datanodeLocalHAIP %u:%s\n", tt + 1, g_node[nodeId].datanode[kk].datanodeLocalHAIP[tt]);
}
(void)fprintf(g_logFilePtr, "datanodeLocalHAPort :%u\n", g_node[nodeId].datanode[kk].datanodeLocalHAPort);
if (g_multi_az_cluster) {
(void)fprintf(g_logFilePtr, "dn_replication_num: %u\n", g_dn_replication_num);
for (uint32 dnId = 0; dnId < g_dn_replication_num - 1; dnId++) {
(void)fprintf(g_logFilePtr, "datanodePeer%uDataPath :%s\n", dnId,
g_node[nodeId].datanode[kk].peerDatanodes[dnId].datanodePeerDataPath);
for (uint32 tt = 0; tt < g_node[nodeId].datanode[kk].peerDatanodes[dnId].datanodePeerHAListenCount;
tt++) {
(void)fprintf(g_logFilePtr, "datanodePeer%uHAIP %u:%s\n", dnId, tt + 1,
g_node[nodeId].datanode[kk].peerDatanodes[dnId].datanodePeerHAIP[tt]);
}
(void)fprintf(g_logFilePtr, "datanodePeer%uHAPort :%u\n", dnId,
g_node[nodeId].datanode[kk].peerDatanodes[dnId].datanodePeerHAPort);
}
} else {
(void)fprintf(g_logFilePtr, "datanodePeerDataPath :%s\n", g_node[nodeId].datanode[kk].datanodePeerDataPath);
for (uint32 tt = 0; tt < g_node[nodeId].datanode[kk].datanodePeerHAListenCount; tt++) {
(void)fprintf(
g_logFilePtr, "datanodePeerHAIP %u:%s\n", tt + 1, g_node[nodeId].datanode[kk].datanodePeerHAIP[tt]);
}
(void)fprintf(g_logFilePtr, "datanodePeerHAPort :%u\n", g_node[nodeId].datanode[kk].datanodePeerHAPort);
(void)fprintf(g_logFilePtr, "datanodePeer2DataPath :%s\n",
g_node[nodeId].datanode[kk].datanodePeer2DataPath);
for (uint32 tt = 0; tt < g_node[nodeId].datanode[kk].datanodePeer2HAListenCount; tt++) {
(void)fprintf(g_logFilePtr, "datanodePeer2HAIP %u:%s\n", tt + 1,
g_node[nodeId].datanode[kk].datanodePeer2HAIP[tt]);
}
(void)fprintf(g_logFilePtr, "datanodePeer2HAPort :%u\n", g_node[nodeId].datanode[kk].datanodePeer2HAPort);
}
}
}
static void RecordEtcdInfo(uint32 nodeId)
{
if (g_node[nodeId].etcd != 1) {
return;
}
(void)fprintf(g_logFilePtr, "etcdName :%s\n", g_node[nodeId].etcdName);
(void)fprintf(g_logFilePtr, "etcdDataPath :%s\n", g_node[nodeId].etcdDataPath);
for (uint32 kk = 0; kk < g_node[nodeId].etcdClientListenIPCount; kk++) {
(void)fprintf(g_logFilePtr, "etcdClientListenIPs %u:%s\n", kk + 1, g_node[nodeId].etcdClientListenIPs[kk]);
}
(void)fprintf(g_logFilePtr, "etcdClientListenPort :%u\n", g_node[nodeId].etcdClientListenPort);
for (uint32 kk = 0; kk < g_node[nodeId].etcdHAListenIPCount; kk++) {
(void)fprintf(g_logFilePtr, "etcdHAListenIPs %u:%s\n", kk + 1, g_node[nodeId].etcdHAListenIPs[kk]);
}
(void)fprintf(g_logFilePtr, "etcdHAListenPort :%u\n", g_node[nodeId].etcdHAListenPort);
}
static void do_view()
{
if (!SetOutputFile(g_logFileSet, g_logFile)) {
write_runlog(ERROR, "Execution failed.\n");
return;
}
RecordCommonInfo();
for (uint32 ii = 0; ii < g_node_num; ii++) {
if (g_nodeIdSet && ((ii + 1) != g_commandOperationNodeId)) {
continue;
}
RecordNodeInfo(ii);
RecordCmsInfo(ii);
RecordCmaInfo(ii);
#ifdef ENABLE_MULTIPLE_NODES
RecordGtmInfo(ii, g_logFilePtr);
RecordCnInfo(ii, g_logFilePtr);
#endif
RecordDnInfo(ii);
RecordEtcdInfo(ii);
}
if (g_logFileSet && (g_logFilePtr != NULL)) {
(void)fclose(g_logFilePtr);
g_logFilePtr = NULL;
}
}
bool do_dynamic_view()
{
int fd;
ssize_t returnCode;
char clusterDynamicConfig[MAXPGPATH] = {0};
int ret = snprintf_s(clusterDynamicConfig, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, DYNAMC_CONFIG_FILE);
securec_check_intval(ret, (void)ret);
check_input_for_security(clusterDynamicConfig);
canonicalize_path(clusterDynamicConfig);
fd = open(clusterDynamicConfig, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR);
if (fd < 0) {
char errBuffer[ERROR_LIMIT_LEN];
write_runlog2(FATAL,
errcode(ERRCODE_OPEN_FILE_FAILURE),
errmsg("Failed to open the dynamic config file \"%s\".", DYNAMC_CONFIG_FILE),
errdetail("reason : %s.", strerror_r(errno, errBuffer, ERROR_LIMIT_LEN)),
errmodule(MOD_CMCTL),
errcause("The dynamic config file permission is insufficient."),
erraction("Please check the dynamic config file."));
return false;
}
size_t header_size = sizeof(dynamicConfigHeader);
size_t header_aglinment_size =
(header_size / AGLINMENT_SIZE + ((header_size % AGLINMENT_SIZE == 0) ? 0 : 1)) * AGLINMENT_SIZE;
dynamicConfigHeader *g_dynamic_header = (dynamicConfigHeader *)malloc(header_aglinment_size);
if (g_dynamic_header == NULL) {
write_runlog2(FATAL, errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("Failed to malloc memory, size = %lu.", header_aglinment_size),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("out of memeory."),
erraction("Please check the system memory and try again."));
(void)close(fd);
return false;
}
returnCode = read(fd, g_dynamic_header, header_aglinment_size);
if (returnCode != (ssize_t)header_aglinment_size) {
write_runlog(FATAL, "read header failed!\n");
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
return false;
}
returnCode = lseek(fd, (ssize_t)(header_aglinment_size), SEEK_SET);
if (returnCode < 0) {
write_runlog(FATAL, "seek header failed!\n");
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
return false;
}
size_t cms_state_timeline_size = sizeof(dynamic_cms_timeline);
dynamic_cms_timeline *g_timeline = (dynamic_cms_timeline *)malloc(cms_state_timeline_size);
if (g_timeline == NULL) {
write_runlog2(FATAL,
errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Failed to malloc memory, size = %lu.", cms_state_timeline_size),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("out of memeory."),
erraction("Please check the system memory and try again."));
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
return false;
}
returnCode = read(fd, g_timeline, cms_state_timeline_size);
if (returnCode != (ssize_t)cms_state_timeline_size) {
write_runlog(FATAL, "read timeline failed!\n");
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
FREE_AND_RESET(g_timeline);
return false;
}
returnCode = lseek(fd, (ssize_t)(cms_state_timeline_size + header_aglinment_size), SEEK_SET);
if (returnCode < 0) {
write_runlog(FATAL, "seek timeline failed!\n");
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
FREE_AND_RESET(g_timeline);
return false;
}
size_t roleGroupsBytes = 0;
if (CheckDynamicRelationCount(g_dynamic_header->relationCount, &roleGroupsBytes) != CM_SUCCESS) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("Invalid relationCount %u in dynamic config file, max is %u.",
g_dynamic_header->relationCount, MAX_DYNAMIC_CONFIG_RELATION_COUNT),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("The dynamic config file is corrupted or tampered."),
erraction("Please check or regenerate the dynamic config file."));
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
FREE_AND_RESET(g_timeline);
return false;
}
cm_instance_role_group *g_instance_role_group_ptr =
(cm_instance_role_group *)malloc(roleGroupsBytes);
if (g_instance_role_group_ptr == NULL) {
write_runlog2(FATAL, errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("Failed to malloc memory, size = %lu.", roleGroupsBytes),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("out of memeory."),
erraction("Please check the system memory and try again."));
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
FREE_AND_RESET(g_timeline);
return false;
}
returnCode = read(fd, g_instance_role_group_ptr, roleGroupsBytes);
if (returnCode != (ssize_t)roleGroupsBytes) {
write_runlog(FATAL, "read instance role failed!\n");
(void)close(fd);
FREE_AND_RESET(g_dynamic_header);
FREE_AND_RESET(g_instance_role_group_ptr);
FREE_AND_RESET(g_timeline);
return false;
}
(void)close(fd);
for (uint32 i = 0; i < g_dynamic_header->relationCount; i++) {
if (g_instance_role_group_ptr[i].instanceMember[0].instanceType == INSTANCE_TYPE_COORDINATE) {
(void)printf("node : %u\n", g_instance_role_group_ptr[i].instanceMember[0].node);
(void)printf("instance_id : %u\n", g_instance_role_group_ptr[i].instanceMember[0].instanceId);
if (g_instance_role_group_ptr[i].instanceMember[0].role == INSTANCE_ROLE_DELETED) {
(void)printf("role : Deleted\n\n");
} else {
(void)printf("role : Not deleted\n\n");
}
}
}
FREE_AND_RESET(g_dynamic_header);
FREE_AND_RESET(g_instance_role_group_ptr);
FREE_AND_RESET(g_timeline);
return true;
}
* @Description: Check user input AZ name.
*/
static void checkCmdAZName(const char* azName)
{
for (uint32 i = 0; i < g_node_num; i++) {
if (strcmp(g_node[i].azName, azName) == 0) {
g_command_operation_azName = xstrdup(azName);
return;
}
}
if (strcmp("ALL", azName) == 0) {
g_availabilityZoneCommand = true;
} else {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("unrecognized AZ name \"%s\".", azName),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("The parameter(%s) entered by the user is incorrect.", azName),
erraction("Please check the parameter entered by the user and try again."));
if (g_logFileSet && (g_logFilePtr != NULL)) {
(void)fclose(g_logFilePtr);
g_logFilePtr = NULL;
}
exit(1);
}
}
* @Description: Check user input AZ name.
*/
static void CheckMinorityAZName(const char *azName)
{
bool found = false;
for (uint32 i = 0; i < g_node_num; i++) {
if (strcmp(g_node[i].azName, azName) == 0) {
FREE_AND_RESET(g_commandMinortityAzName);
g_commandMinortityAzName = xstrdup(azName);
found = true;
break;
}
}
if (!found) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("unrecognized minorityAz name \"%s\".", azName),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("The parameter(%s) entered by the user is incorrect.", azName),
erraction("Please check the parameter entered by the user and try again."));
exit(1);
}
}
* @Description: Check if user input AZ name is in cluster.
*/
static bool checkAZNameInCluster(const char* azName)
{
uint32 i;
bool isAzNameInCluster = false;
for (i = 0; i < g_node_num; i++) {
if (strcmp(g_node[i].azName, azName) == 0) {
isAzNameInCluster = true;
break;
}
}
return isAzNameInCluster;
}
* @brief: Get the logger path from the environment variable. And set the log file path.
*
* @return: void
*/
static void InitializeLogger()
{
char logPath[MAXPGPATH] = {0};
prefix_name = g_progname;
(void)logfile_init();
int ret = cmctl_getenv("GAUSSLOG", logPath, MAXPGPATH - 1);
if (ret == EOK) {
check_input_for_security(logPath);
ret = snprintf_s(sys_log_path, MAXPGPATH, MAXPGPATH - 1, "%s/cm/%s/", logPath, "cm_ctl");
securec_check_intval(ret, (void)ret);
} else {
ret = snprintf_s(sys_log_path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/", g_appPath);
securec_check_intval(ret, (void)ret);
}
if (sys_log_path[0] == '/') {
(void)CmMkdirP(sys_log_path, S_IRWXU);
} else {
(void)mkdir(sys_log_path, S_IRWXU);
}
log_min_messages = DEBUG1;
}
static bool CtlIsSharedStorageMode()
{
char env[MAX_PATH_LEN] = {0};
if (cm_getenv("DORADO_REARRANGE", env, sizeof(env), DEBUG5) != EOK) {
return false;
}
write_runlog(DEBUG1, "Get DORADO_REARRANGE success, is shared storage mode.\n");
return true;
}
static void init_ctl_global_variable()
{
int ret = GetHomePath(g_appPath, sizeof(g_appPath), DEBUG5);
if (ret == EOK) {
ret =
snprintf_s(g_logicClusterListPath, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, LOGIC_CLUSTER_LIST);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(manual_start_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, CLUSTER_MANUAL_START);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(
instance_manual_start_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, INSTANCE_MANUAL_START);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(
cluster_manual_starting_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, CLUSTER_MANUAL_STARTING);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(etcd_manual_start_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, ETCD_MANUAL_START);
securec_check_intval(ret, (void)ret);
#ifndef ENABLE_MULTIPLE_NODES
ret = snprintf_s(g_ltranManualStartFile, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, g_ltranManualStart);
securec_check_intval(ret, (void)ret);
canonicalize_path(g_ltranManualStartFile);
ret =
snprintf_s(g_libnetManualStartFile, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, g_libnetManualStart);
securec_check_intval(ret, (void)ret);
canonicalize_path(g_libnetManualStartFile);
#else
ret = snprintf_s(resuming_cn_stop_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, RESUMING_CN_STOP);
securec_check_intval(ret, (void)ret);
#endif
ret = snprintf_s(minority_az_start_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, MINORITY_AZ_START);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(g_minorityAzArbitrateFile, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s",
g_appPath, MINORITY_AZ_ARBITRATE);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(cluster_static_config, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, STATIC_CONFIG_FILE);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(cluster_dynamic_config, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, DYNAMC_CONFIG_FILE);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(cm_server_bin, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, CM_SERVER_BIN_NAME);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(result_path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/result", g_appPath);
securec_check_intval(ret, (void)ret);
canonicalize_path(result_path);
ret = snprintf_s(hosts_path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/hosts", g_appPath);
securec_check_intval(ret, (void)ret);
canonicalize_path(hosts_path);
ret = snprintf_s(pssh_out_path, MAXPGPATH, MAXPGPATH - 1, "%s/bin/pssh.out", g_appPath);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(g_tlsPath.caFile, ETCD_MAX_PATH_LEN, ETCD_MAX_PATH_LEN - 1,
"%s/share/sslcert/etcd/etcdca.crt", g_appPath);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(g_tlsPath.crtFile, ETCD_MAX_PATH_LEN, ETCD_MAX_PATH_LEN - 1,
"%s/share/sslcert/etcd/client.crt", g_appPath);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(g_tlsPath.keyFile, ETCD_MAX_PATH_LEN, ETCD_MAX_PATH_LEN - 1,
"%s/share/sslcert/etcd/client.key", g_appPath);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(manual_pause_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, CLUSTER_MANUAL_PAUSE);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(manual_walrecord_file, MAXPGPATH, MAXPGPATH - 1, "%s/bin/%s", g_appPath, CLUSTER_MANUAL_WALRECORD);
securec_check_intval(ret, (void)ret);
} else {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("Get GAUSSHOME failed."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("The environment variable(\"GAUSSHOME\") is incorrectly configured."),
erraction("Please check the environment variable(\"GAUSSHOME\")."));
exit(1);
}
InitializeLogger();
ret = cmctl_getenv("MPPDB_ENV_SEPARATE_PATH", mpp_env_separate_file, sizeof(mpp_env_separate_file));
if (ret == EOK) {
check_input_for_security(mpp_env_separate_file);
}
pw = getpwuid(getuid());
if (pw == NULL || pw->pw_name == NULL) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("Get current user name failed."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("N/A"), erraction("Please check the environment."));
exit(1);
}
g_isSharedStorageMode = CtlIsSharedStorageMode();
}
static int CheckInputParameter()
{
if (g_bin_name == NULL) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-B option must be specified."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
check_input_for_security(g_bin_name);
if (g_bin_path == NULL) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-T option must be specified.\n"), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
check_input_for_security(g_bin_path);
return 0;
}
static int CheckStopParameter()
{
bool cond = (ctl_command == STOP_COMMAND) && (shutdown_mode_num == SMART_MODE) && (g_commandOperationNodeId > 0);
if (cond) {
write_runlog2(ERROR,
errcode(ERRCODE_PARAMETER_FAILURE), errmsg("can't stop one node or instance with -m normal."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctl_command == STOP_COMMAND) && (shutdown_mode_num == RESUME_MODE) && (g_commandOperationNodeId > 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("can't stop one node or instance with -m resume."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctl_command == STOP_COMMAND) && (shutdown_mode_num == RESUME_MODE) &&
(g_command_operation_azName != NULL);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("can't stop one availability zone with -m resume."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int SetAndGetCheckParameter()
{
bool cond = (log_level_set == NULL) && (cm_arbitration_mode_set == NULL) && (cm_switchover_az_mode_set == NULL) &&
(cm_logic_cluster_restart_mode_set == NULL) && (g_cmsPromoteMode == NULL) && (ctl_command == CM_SET_COMMAND);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("log level or cm server arbitration mode must be specified."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = ((log_level_set != NULL) || (cm_arbitration_mode_set != NULL) || (cm_switchover_az_mode_set != NULL) ||
(cm_logic_cluster_restart_mode_set != NULL)) && (g_cmsPromoteMode == NULL) && (ctl_command == CM_GET_COMMAND);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("log level or cm server arbitration mode need not be specified."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int QueryCheckParameter(const CtlOption *ctx)
{
bool cond = (ctl_command == CM_QUERY_COMMAND) && (g_cmData[0] != '\0') && !g_commandRelationship &&
(g_commandOperationNodeId != 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-R is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctl_command == CM_QUERY_COMMAND) && (g_cmData[0] == '\0') && g_commandRelationship &&
(g_commandOperationNodeId != 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-D is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctl_command == CM_QUERY_COMMAND) && (g_cmData[0] != '\0') && !g_commandRelationship &&
(g_commandOperationNodeId == 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-n and -R are needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctl_command == CM_QUERY_COMMAND) && (g_cmData[0] == '\0') && g_commandRelationship &&
(g_commandOperationNodeId == 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-n and -D are needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctl_command == CM_QUERY_COMMAND) && ((do_force != 0) || switchover_all_quick ||
ctx->switchover.switchoverAll || ctx->switchover.switchoverFull || ctx->build.isNeedCmsBuild);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("unsupported parameters."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckAbnormal(const CtlOption *ctx)
{
if (ctl_command == NO_COMMAND) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("no operation specified."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
if (ctx->comm.nodeId == 0) {
return 0;
}
uint32 nodeIndex = get_node_index(ctx->comm.nodeId);
if (nodeIndex == INVALID_NODE_NUM) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n node(%u) is invalid.", ctx->comm.nodeId),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckCommandNotSwitchoverAll(const CtlOption *ctx)
{
bool cond = (g_commandOperationNodeId == 0) ||
(get_node_index(g_commandOperationNodeId) >= g_nodeHeader.nodeCount);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n node(%u) is invalid.", g_commandOperationNodeId),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (ctx->build.parallel < PARALLELISM_MIN) || (ctx->build.parallel > PARALLELISM_MAX);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-j parallelism(%d) is invalid.", ctx->build.parallel),
errdetail("it must in the range of 0 to 16."), errmodule(MOD_CMCTL),
errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckCommandSwitchoverAll(void)
{
if (g_commandOperationNodeId != 0 || g_cmData[0] != '\0') {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("switchover -a don't need other parameter."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckCommandQueryLcOperation(void)
{
if (g_coupleQuery) {
return 0;
}
if (ctl_command == CM_QUERY_COMMAND && lc_operation) {
if (g_detailQuery) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-C is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
} else {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-Cv is needed."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
}
return 1;
}
return 0;
}
static int CheckCommandQuery(void)
{
bool cond = (ctl_command == CM_QUERY_COMMAND) && (!g_availabilityZoneCommand) &&
(g_command_operation_azName != NULL);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-z value must be \"ALL\" when query mppdb cluster."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (g_coupleQuery && !g_detailQuery) || (g_paralleRedoState && !g_detailQuery);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-v is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (g_formatQuery && !g_coupleQuery && !g_detailQuery);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-Cv is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (g_formatQuery && !g_coupleQuery && g_detailQuery);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-C is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
CM_RETURN_INT_IFERR(CheckCommandQueryLcOperation());
cond = (ctl_command == CM_QUERY_COMMAND) && !logic_cluster_query &&
(g_command_operation_lcName != NULL) && (g_logic_cluster_count > 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-L value must be \"ALL\" when query logic cluster."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckCommandExceptSwitchover()
{
bool cond = (g_commandOperationNodeId > 0) &&
(get_node_index(g_commandOperationNodeId) >= g_nodeHeader.nodeCount);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n node(%u) is invalid.", g_commandOperationNodeId),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = (g_cmData[0] != '\0') && !g_commandOperationNodeId;
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-n node is needed."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
CM_RETURN_INT_IFERR(CheckStopParameter());
cond = (g_balanceQuery || g_ipQuery || g_dataPathQuery || g_fencedUdfQuery || g_abnormalQuery || g_portQuery ||
g_startStatusQuery) && !g_coupleQuery;
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("%s: -C is needed.", g_progname),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
CM_RETURN_INT_IFERR(CheckCommandQuery());
cond = (ctl_command == RESTART_COMMAND) && !logic_cluster_restart && (g_command_operation_lcName != NULL) &&
(g_logic_cluster_count > 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("unrecognized LC name \"%s\".", g_command_operation_lcName), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckCommandCore(const CtlOption *ctx)
{
bool condNotSwitchoverAll = (ctl_command == CM_SWITCHOVER_COMMAND && !ctx->switchover.switchoverAll &&
!ctx->switchover.switchoverFull && (g_command_operation_azName == NULL && !switchover_all_quick)) ||
(ctl_command == CM_BUILD_COMMAND && !(ctx->build.isNeedCmsBuild && (g_commandOperationNodeId == 0)));
bool condSwitchoverAll = (ctl_command == CM_SWITCHOVER_COMMAND) && ctx->switchover.switchoverAll;
bool condExceptSwitchover = (ctl_command == START_COMMAND) || (ctl_command == STOP_COMMAND) ||
(ctl_command == CM_QUERY_COMMAND) || (ctl_command == RESTART_COMMAND) ||
(ctl_command == CM_FINISHREDO_COMMAND);
if (condNotSwitchoverAll) {
CM_RETURN_INT_IFERR(CheckCommandNotSwitchoverAll(ctx));
} else if (condSwitchoverAll) {
CM_RETURN_INT_IFERR(CheckCommandSwitchoverAll());
} else if (condExceptSwitchover) {
CM_RETURN_INT_IFERR(CheckCommandExceptSwitchover());
}
return 0;
}
static void CheckCommandOperationNodeId(void)
{
if ((g_cmData[0] == '\0') && g_commandOperationNodeId != 0) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-D is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
} else if ((g_cmData[0] != '\0') && g_commandOperationNodeId == 0) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-n is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
} else {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-n and -D are needed."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
}
}
static int CheckCommandRelationship(const CtlOption *ctx)
{
bool cond = (ctl_command == CM_QUERY_COMMAND) && (g_cmData[0] != '\0') && g_commandRelationship &&
(g_commandOperationNodeId == 0);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-n is needed."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
CM_RETURN_INT_IFERR(QueryCheckParameter(ctx));
cond = g_commandRelationship && ((g_cmData[0] == '\0') || g_commandOperationNodeId == 0);
if (cond) {
CheckCommandOperationNodeId();
return 1;
}
return 0;
}
static int CheckForOtherCommands(const CtlOption *ctx)
{
bool cond = (ctx->switchover.switchoverAll && g_commandOperationNodeId) ||
(ctx->switchover.switchoverFull && g_commandOperationNodeId) ||
(g_command_operation_azName != NULL && ctx->switchover.switchoverAll) ||
(g_command_operation_azName != NULL && ctx->switchover.switchoverFull) ||
(ctx->switchover.switchoverAll && ctx->switchover.switchoverFull);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("Please check the usage of switchover."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
cond = ((g_command_operation_azName != NULL) && g_commandOperationNodeId);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n and -z cannot be specified at the same time."),
errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
#ifdef ENABLE_MULTIPLE_NODES
cond = cn_resumes_restart && (g_command_operation_azName != NULL || g_commandOperationNodeId);
if (cond) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-m cannot be specified at the same time with -n or -z."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
#endif
CM_RETURN_INT_IFERR(CheckCommandCore(ctx));
CM_RETURN_INT_IFERR(CheckCommandRelationship(ctx));
cond = (ctl_command == CM_SET_COMMAND) && (ctx->guc.nodeType != NODE_TYPE_UNDEF);
if (cond) {
if (CheckGucSetParameter(ctx) != CM_SUCCESS) {
return 1;
}
} else {
CM_RETURN_INT_IFERR(SetAndGetCheckParameter());
}
return 0;
}
static int CheckCtlInputAzName(void)
{
bool condition = (g_command_operation_azName != NULL) && !checkAZNameInCluster(g_command_operation_azName);
if (condition) {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("There is no \"%s\" information in cluster.", g_command_operation_azName), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
return 0;
}
static int CheckCtlInputParameter(const CtlOption *ctx)
{
CM_RETURN_INT_IFERR(CheckAbnormal(ctx));
bool condition = (ctl_command == CM_SWITCHOVER_COMMAND && !ctx->switchover.switchoverAll &&
!ctx->switchover.switchoverFull && (g_command_operation_azName == NULL && !switchover_all_quick)) ||
(ctl_command == CM_BUILD_COMMAND && !ctx->build.isNeedCmsBuild) || ctl_command == CM_REMOVE_COMMAND ||
ctl_command == CM_STARTCM_COMMAND || ctl_command == CM_STOPCM_COMMAND || ctl_command == CM_DISABLE_COMMAND ||
ctl_command == CM_ENCRYPT_COMMAND;
getWalrecordMode();
if (condition) {
if (!g_enableWalRecord && g_cmData[0] == '\0') {
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("no data directory specified."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
return 1;
}
}
if (ctl_command != CM_CHECK_COMMAND) {
CM_RETURN_INT_IFERR(CheckForOtherCommands(ctx));
} else {
CM_RETURN_INT_IFERR(CheckInputParameter());
}
CM_RETURN_INT_IFERR(CheckCtlInputAzName());
return 0;
}
void stop_flag(void)
{
got_stop = true;
if (!g_execute_cmctl_success) {
cm_sleep(6);
}
}
static void PathStrCheck(const char *inPath, char *outPath)
{
if (inPath == NULL) {
return;
}
size_t length = strlen(inPath);
if (length == 0) {
return;
}
char tempChar;
while ((tempChar = *inPath++) != '\0') {
if (tempChar == '/' && *inPath == '/') {
continue;
}
*outPath = tempChar;
outPath++;
}
if (length > 1 && outPath[strlen(outPath) - 1] == '/') {
outPath[strlen(outPath) - 1] = '\0';
}
return;
}
static void ReleaseResource()
{
if (CmServer_conn != NULL) {
CMPQfinish(CmServer_conn);
CmServer_conn = NULL;
}
FreeSslOpton();
FREE_AND_RESET(g_logFile);
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
FREE_AND_RESET(hotpatch_path);
#endif
FreeDdbInfo();
}
static status_t GetCtlCommand(int argc, char **argv)
{
if (optind >= argc) {
return CM_SUCCESS;
}
if (ctl_command != NO_COMMAND) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("too many command-line arguments (first is \"%s\").", argv[optind]), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
return CM_ERROR;
}
unordered_map<string, CtlCommand>::iterator it = g_optToCommand.find(argv[optind]);
if (it != g_optToCommand.end()) {
ctl_command = it->second;
} else {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("unrecognized operation mode \"%s\".", argv[optind]), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
return CM_ERROR;
}
++optind;
return CM_SUCCESS;
}
void InitCtlOptionParams(CtlOption *ctx)
{
errno_t rc = memset_s(ctx, sizeof(CtlOption), 0, sizeof(CtlOption));
securec_check_errno(rc, (void)rc);
ctx->guc.keyMod = SERVER_MODE;
ctx->dcfOption.group = -1;
ctx->dcfOption.priority = -1;
}
status_t GetSetParameterAndValue(char *str, GucOption *gucCtx)
{
char *para;
char *val;
char *buf;
if (str[0] == '=') {
write_runlog(LOG, "need input parameter.\n");
return CM_ERROR;
}
para = strtok_s(str, "=", &buf);
if (para == NULL) {
write_runlog(LOG, "need input parameter.\n");
return CM_ERROR;
}
val = strtok_s(NULL, "=", &buf);
if (val == NULL) {
write_runlog(LOG, "need input value.\n");
return CM_ERROR;
}
if (strcmp(buf, "") != 0) {
write_runlog(LOG, "too many command line arguments.\n");
return CM_ERROR;
}
gucCtx->parameter = xstrdup(para);
gucCtx->value = xstrdup(val);
return CM_SUCCESS;
}
static status_t CheckKeyMode(const char* mode, GucOption *gucCtx)
{
size_t sLen = strlen("server");
size_t clen = strlen("client");
if (mode == NULL || mode[0] == '\0' || (strcmp(mode, "-D") == 0)) {
write_runlog(LOG, "-M is invalid, try \"%s --help\" for more information.\n", g_progname);
return CM_ERROR;
}
if ((strncmp(mode, "server", sLen) == 0) && (mode[sLen] == '\0')) {
gucCtx->keyMod = SERVER_MODE;
} else if ((strncmp(mode, "client", clen) == 0) && (mode[clen] == '\0')) {
gucCtx->keyMod = CLIENT_MODE;
} else {
write_runlog(LOG, "mode \"%s\" is not support, try \"%s --help\" for more information.\n", mode, g_progname);
return CM_ERROR;
}
return CM_SUCCESS;
}
static void CheckArgcType(int argc, const char * const *argv)
{
if (argc > 1) {
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) {
DoHelp(g_progname);
exit(0);
} else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) {
(void)puts("cm_ctl " DEF_CM_VERSION);
exit(0);
}
}
}
static int MakeupCmdline(int argc, char** argv)
{
if (argc > 1 && (strcmp(argv[1], "ddb") == 0)) {
return 0;
}
uint32 cmdLen;
int ret = sprintf_s(g_cmdLine, MAX_PATH_LEN, "%s", argv[0]);
securec_check_intval(ret, (void)ret);
cmdLen = (uint32)strlen(g_cmdLine);
for (int32 i = 1; i < argc; i++) {
uint32 optLen = ((uint32)strlen(argv[i]) + 1);
if ((cmdLen + optLen) >= MAX_PATH_LEN) {
(void)printf(_("cmd is too long, %u.\n"), (uint32)(cmdLen + optLen));
return CM_EXIT;
}
ret = sprintf_s(g_cmdLine + cmdLen, MAX_PATH_LEN - cmdLen, " %s", argv[i]);
securec_check_intval(ret, (void)ret);
cmdLen += optLen;
}
return 0;
}
static void CtlDccCommand(int argc, char** argv)
{
if (argc > 1 && (strcmp(argv[1], "ddb") == 0)) {
write_runlog(DEBUG1, "ip: \"%s\", cmd: cm_ctl ddb ...\n", g_currentNode->sshChannel[0]);
DoDccCmd(argc, argv);
exit(0);
}
}
static void MatchCmdArgb(CtlOption *ctlCtx)
{
if (optarg != NULL && strcmp("full", optarg) == 0) {
ctlCtx->build.doFullBuild = 1;
} else {
if (optarg == NULL) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("unrecognized build mode."), errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
}
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("unrecognized build mode \"%s\".", optarg), errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
}
}
static void MatchCmdArgD(bool *setDataPath)
{
if (optarg != NULL) {
if (strlen(optarg) > (MAX_PATH_LEN - 1)) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-D path is too long.\n"), errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
}
char* envVar = (char*)pg_malloc(strlen(optarg) + 8);
*setDataPath = true;
char *cmDataPath = xstrdup(optarg);
check_input_for_security(cmDataPath);
char outPath[MAX_PATH_LEN] = {0};
PathStrCheck(cmDataPath, outPath);
int ret = snprintf_s(cmDataPath, strlen(outPath) + 1, strlen(outPath), "%s", outPath);
securec_check_intval(ret, (void)ret);
ret = snprintf_s(envVar, strlen(optarg) + 8, strlen(optarg) + 7, "CMDATA=%s", cmDataPath);
securec_check_intval(ret, (void)ret);
(void)putenv(envVar);
* We could pass PGDATA just in an environment
* variable but we do -D too for clearer postmaster
* 'ps' display
*/
FREE_AND_RESET(pgdata_opt);
pgdata_opt = (char*)pg_malloc(strlen(cmDataPath) + 7);
ret = snprintf_s(pgdata_opt, strlen(cmDataPath) + 7, strlen(cmDataPath) + 6,
"-D \"%s\" ", cmDataPath);
securec_check_intval(ret, (void)ret);
check_input_for_security(pgdata_opt);
FREE_AND_RESET(cmDataPath);
} else {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-D path is invalid."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
}
static void MatchCmdArgn(CtlOption *ctlCtx)
{
if (CM_is_str_all_digit(optarg) != 0 || CmAtoi(optarg, 0) == 0) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n node(%s) is invalid.", optarg), errdetail("N/A"),
errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
if (g_nodeIdSet) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n and -N can not be set at the same time."), errdetail("N/A"),
errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
g_nodeIdSet = true;
g_commandOperationNodeId = (uint32)CmAtoi(optarg, 0);
ctlCtx->comm.nodeId = static_cast<uint32>(CmAtoi(optarg, 0));
}
static void MatchCmdArgN(void)
{
if (g_nodeIdSet) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-n and -N can not be set at the same time."), errdetail("N/A"),
errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
g_nodeIdSet = true;
g_commandOperationNodeId = g_currentNode->node;
}
static void MatchCmdArgI(void)
{
if (CM_is_str_all_digit(optarg) != 0 || CmAtoi(optarg, 0) == 0) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-I instance(%s) is invalid.", optarg), errdetail("N/A"),
errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
g_commandOperationInstanceId = (uint32)CmAtoi(optarg, 0);
}
#ifdef ENABLE_MULTIPLE_NODES
static void MatchCmdArgR(void)
{
g_commandRelationship = true;
if (g_only_dn_cluster) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-R only support when the cluster is single-inst."), errdetail("N/A"),
errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
}
}
#endif
static void MatchCmdArgt(void)
{
if (CM_is_str_all_digit(optarg) != 0) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("-t time is invalid."), errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
wait_seconds_set = true;
g_waitSeconds = CmAtoi(optarg, 0);
}
#ifdef ENABLE_MULTIPLE_NODES
static void MatchCmdArgL(void)
{
if (optarg != NULL) {
lc_operation = true;
if (!checkCmdLcName(optarg)) {
exit(1);
}
}
}
#endif
static void MatchCmdArg1(void)
{
if (optarg != NULL) {
FREE_AND_RESET(log_level_set);
log_level_set = xstrdup(optarg);
} else {
log_level_get = true;
}
}
static void MatchCmdArg2(void)
{
if (optarg != NULL) {
FREE_AND_RESET(cm_arbitration_mode_set);
cm_arbitration_mode_set = xstrdup(optarg);
} else {
cm_arbitration_mode_get = true;
}
}
static void MatchCmdArg3(void)
{
if (optarg != NULL) {
FREE_AND_RESET(cm_switchover_az_mode_set);
cm_switchover_az_mode_set = xstrdup(optarg);
} else {
cm_switchover_az_mode_get = true;
}
}
static void MatchCmdArg4(void)
{
if (optarg != NULL) {
FREE_AND_RESET(cm_logic_cluster_restart_mode_set);
cm_logic_cluster_restart_mode_set = xstrdup(optarg);
}
}
static void MatchCmdArgDcfXmode(void)
{
if (optarg != NULL) {
FREE_AND_RESET(g_dcfXMode);
g_dcfXMode = xstrdup(optarg);
}
}
static void MatchCmdArgDcfVoteNum(void)
{
if (CM_is_str_all_digit(optarg) != 0) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("-votenum is invalid."),
errdetail("N/A"), errmodule(MOD_CMCTL),
errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
g_dcfVoteNum = CmAtoi(optarg, 0);
}
static void MatchCmdArgDcfRole(CtlOption *ctlCtx)
{
if (optarg != NULL) {
FREE_AND_RESET(ctlCtx->dcfOption.role);
ctlCtx->dcfOption.role = xstrdup(optarg);
}
}
static void MatchCmdArgDcfGroup(CtlOption *ctlCtx)
{
if (CM_is_str_all_digit(optarg) != 0 || CmAtoi(optarg, -1) < 0) {
write_runlog(ERROR, "dcfGroup is invalid.\n");
DoAdvice();
ctlCtx->dcfOption.group = ErrorCode;
return;
}
ctlCtx->dcfOption.group = CmAtoi(optarg, -1);
}
static void MatchCmdArgDcfPriority(CtlOption *ctlCtx)
{
if (CM_is_str_all_digit(optarg) != 0 || CmAtoi(optarg, -1) < 0) {
write_runlog(ERROR, "dcfPriority is invalid.\n");
DoAdvice();
ctlCtx->dcfOption.priority = ErrorCode;
return;
}
ctlCtx->dcfOption.priority = CmAtoi(optarg, -1);
}
static void MatchCmdArgMinorityAz(void)
{
if (optarg != NULL) {
CheckMinorityAZName(optarg);
}
}
static void MatchCmdArgCmsPmode(void)
{
if (optarg != NULL) {
FREE_AND_RESET(g_cmsPromoteMode);
g_cmsPromoteMode = xstrdup(optarg);
}
}
static void ParseCmdArgsCore(int cmd, bool *setDataPath, CtlOption *ctlCtx)
{
switch (cmd) {
case 'a':
ctlCtx->switchover.switchoverAll = true;
break;
case 'A':
ctlCtx->switchover.switchoverFull = true;
break;
case 'b':
MatchCmdArgb(ctlCtx);
break;
case 'D':
MatchCmdArgD(setDataPath);
break;
case 'f':
do_force = 1;
ctlCtx->switchover.switchoverFast = true;
break;
case 'F':
g_fencedUdfQuery = 1;
break;
case 'l':
g_logFileSet = true;
FREE_AND_RESET(g_logFile);
g_logFile = xstrdup(optarg);
canonicalize_path(g_logFile);
check_input_for_security(g_logFile);
break;
case 'm':
if (optarg != NULL) {
set_mode(optarg);
}
break;
case 'M':
if (CheckKeyMode(optarg, &ctlCtx->guc) != CM_SUCCESS) {
exit(1);
}
break;
case 'n':
MatchCmdArgn(ctlCtx);
break;
case 'N':
MatchCmdArgN();
break;
case 'I':
MatchCmdArgI();
break;
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
case 'P':
if (optarg != NULL) {
hotpatch_path = xstrdup(optarg);
}
break;
case 'E':
if (optarg != NULL) {
hotpatch_exec = xstrdup(optarg);
}
break;
#endif
#ifdef ENABLE_MULTIPLE_NODES
case 'R':
MatchCmdArgR();
break;
#endif
case 'x':
g_abnormalQuery = true;
break;
case 'p':
g_portQuery = true;
break;
case 'q':
switchover_all_quick = true;
break;
case 't':
MatchCmdArgt();
break;
case 'v':
g_detailQuery = true;
break;
case 'w':
g_formatQuery = true;
break;
case 'c':
ctlCtx->build.isNeedCmsBuild = true;
coordinator_dynamic_view = true;
break;
case 'C':
g_coupleQuery = true;
break;
case 'g':
backup_process_query = true;
break;
case 'd':
g_dataPathQuery = true;
break;
case 'i':
g_ipQuery = true;
break;
case 'O':
g_kickStatQuery = true;
break;
case 'u':
g_wormUsageQuery = true;
break;
#ifdef ENABLE_MULTIPLE_NODES
case 'L':
MatchCmdArgL();
break;
#endif
case 'B':
FREE_AND_RESET(g_bin_name);
if (optarg != NULL) {
g_bin_name = xstrdup(optarg);
}
break;
case 'j':
if (optarg != NULL) {
ctlCtx->build.parallel = CmAtoi(optarg, 0);
}
break;
case 's':
g_balanceQuery = true;
break;
case 'S':
g_startStatusQuery = true;
break;
case 'T':
FREE_AND_RESET(g_bin_path);
if (optarg != NULL) {
g_bin_path = xstrdup(optarg);
}
break;
case 'r':
g_paralleRedoState = true;
break;
case 'k':
if (optarg != NULL && GetSetParameterAndValue(optarg, &ctlCtx->guc) == CM_ERROR) {
exit(1);
}
break;
case 'z':
if (optarg != NULL) {
checkCmdAZName(optarg);
}
break;
case 1:
MatchCmdArg1();
break;
case 2:
MatchCmdArg2();
break;
case 3:
MatchCmdArg3();
break;
case 4:
MatchCmdArg4();
break;
case DCF_XMODE:
MatchCmdArgDcfXmode();
break;
case DCF_VOTE_NUM:
MatchCmdArgDcfVoteNum();
break;
case DCF_ROLE_MODE:
MatchCmdArgDcfRole(ctlCtx);
break;
case MINORITY_AZ:
MatchCmdArgMinorityAz();
break;
case CMS_P_MODE:
MatchCmdArgCmsPmode();
break;
case CM_AGENT_MODE:
ctlCtx->guc.nodeType = NODE_TYPE_AGENT;
break;
case CM_SERVER_MODE:
ctlCtx->guc.nodeType = NODE_TYPE_SERVER;
break;
case CM_SWITCH_DDB:
if (optarg != NULL) {
ctlCtx->switchOption.ddbType = xstrdup(optarg);
}
break;
case CM_SWITCH_COMMIT:
ctlCtx->switchOption.isCommit = true;
break;
case CM_SWITCH_ROLLBACK:
ctlCtx->switchOption.isRollback = true;
break;
case CM_SET_PARAM:
ctlCtx->guc.needDoGuc = true;
break;
case DCF_GROUP:
MatchCmdArgDcfGroup(ctlCtx);
break;
case DCF_PRIORITY:
MatchCmdArgDcfPriority(ctlCtx);
break;
case RES_ADD:
ctlCtx->resOpt.mode = RES_OP_ADD;
break;
case RES_EDIT:
ctlCtx->resOpt.mode = RES_OP_EDIT;
break;
case RES_DEL:
ctlCtx->resOpt.mode = RES_OP_DEL;
break;
case RES_CHECK:
ctlCtx->resOpt.mode = RES_OP_CHECK;
break;
case RES_NAME_INPUT:
if (optarg != NULL) {
ctlCtx->resOpt.resName = xstrdup(optarg);
}
break;
case RES_ATTR_INPUT:
if (optarg != NULL) {
ctlCtx->resOpt.resAttr = xstrdup(optarg);
}
break;
case RES_ADD_INST_INPUT:
if (optarg != NULL) {
ctlCtx->resOpt.inst.instName = xstrdup(optarg);
ctlCtx->resOpt.inst.mode = RES_OP_ADD;
}
break;
case RES_DEL_INST_INPUT:
if (optarg != NULL) {
ctlCtx->resOpt.inst.instName = xstrdup(optarg);
ctlCtx->resOpt.inst.mode = RES_OP_DEL;
}
break;
case RES_EDIT_INST_INPUT:
if (optarg != NULL) {
ctlCtx->resOpt.inst.instName = xstrdup(optarg);
ctlCtx->resOpt.inst.mode = RES_OP_EDIT;
}
break;
case RES_INST_ATTR_INPUT:
if (optarg != NULL) {
ctlCtx->resOpt.inst.instAttr = xstrdup(optarg);
}
break;
case RES_LIST:
ctlCtx->resOpt.mode = RES_OP_LIST;
break;
case RES_LIST_INST_INPUT:
ctlCtx->resOpt.inst.mode = RES_OP_LIST;
break;
default:
DoAdvice();
exit(1);
}
}
static void SetCommonDataPath(bool setDataPath, CtlOption *ctlCtx)
{
int ret;
if (setDataPath) {
ret = cmctl_getenv("CMDATA", g_cmData, sizeof(g_cmData));
if (ret != EOK) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("no cm directory specified."), errdetail("N/A"),
errmodule(MOD_CMCTL), errcause("%s: The cmdline entered by the user is incorrect.", g_progname),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
}
check_input_for_security(g_cmData);
}
ctlCtx->comm.dataPath = xstrdup(g_cmData);
}
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
static void CtlHotPatchComand(void)
{
if (ctl_command == CM_HOTPATCH_COMMAND) {
bool is_list = false;
if (hotpatch_check(hotpatch_path, hotpatch_exec, &is_list) != 0) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE),
errmsg("[PATCH-ERROR] hotpatch command or path set error."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
}
}
#endif
static void SetLogicClusterName(void)
{
max_logic_cluster_name_len = (max_logic_cluster_name_len < strlen("logiccluster_name"))
? (uint32)strlen("logiccluster_name") : max_logic_cluster_name_len;
}
static void CtlCheckComandType(void)
{
if (ctl_command != CM_CHECK_COMMAND) {
SetLogicClusterName();
if (g_etcd_num > 0 && g_etcd_num < ETCD_NUM_UPPER_LIMIT) {
status_t st = ServerDdbInit();
if (st != CM_SUCCESS) {
write_runlog2(ERROR, errcode(ERRCODE_ETCD_OPEN_FAILURE), errmsg("Failed to open etcd."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("Etcd is abnoraml."),
erraction("Please check the Cluster Status and try again."));
FreeDdbInfo();
exit(1);
}
}
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
CtlHotPatchComand();
#endif
}
}
static void ExitFlagForCommand(void)
{
bool cond = (ctl_command != CM_CHECK_COMMAND) && (ctl_command != START_COMMAND) &&
(ctl_command != STOP_COMMAND) && (g_etcd_num != 0);
if (cond) {
(void)atexit(stop_flag);
}
}
static void CtlCheckOther(const CtlOption *ctlCtx)
{
if (CheckCtlInputParameter(ctlCtx) != 0) {
DoAdvice();
exit(1);
}
if (g_single_node_cluster && (ctl_command == CM_SWITCHOVER_COMMAND || ctl_command == CM_BUILD_COMMAND)) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("no standby datanode in single node cluster."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
DoAdvice();
exit(1);
}
ExitFlagForCommand();
}
#ifdef ENABLE_MULTIPLE_NODES
static void DoRestartCommand(void)
{
if (logic_cluster_restart && (g_logic_cluster_count > 0)) {
do_logic_cluster_restart();
} else if (g_logic_cluster_count == 0) {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("restart logic cluster failed."),
errdetail("there are no logic clusters, can't do restart."), errmodule(MOD_CMCTL),
errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
} else {
write_runlog2(FATAL, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("restart logic cluster failed"),
errdetail("-L is need."), errmodule(MOD_CMCTL),
errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
exit(1);
}
}
#endif
int GetWormUsage()
{
FILE *fp;
char buffer[256];
int usage = -1;
fp = popen("grcmd usage", "r");
if (fp == NULL) {
perror("Failed to run command");
return usage;
}
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
char *usage_str = strstr(buffer, "Usage:");
if (usage_str != NULL) {
char *percent_ptr = usage_str + strlen("Usage:");
while (*percent_ptr && !isdigit(*percent_ptr)) {
percent_ptr++;
}
if (*percent_ptr) {
usage = atoi(percent_ptr);
break;
}
}
}
pclose(fp);
return usage;
}
static void DoQueryCommand(int *status)
{
if (backup_process_query) {
*status = do_global_barrier_query();
} else if (g_kickStatQuery) {
*status = DoKickOutStatQuery();
} else {
if (g_enableWalRecord && g_wormUsageQuery) {
g_wormUsage = GetWormUsage();
}
*status = do_query();
}
if (g_logFileSet && (g_logFilePtr != NULL)) {
(void)fclose(g_logFilePtr);
g_logFilePtr = NULL;
}
}
static void DoSetCommand(int *status, CtlOption *ctlCtx)
{
if (ctlCtx->guc.needDoGuc || ctlCtx->guc.nodeType != NODE_TYPE_UNDEF) {
ctlCtx->guc.gucCommand = SET_CONF_COMMAND;
*status = DoGuc(ctlCtx);
} else {
*status = do_set();
}
}
static int DoViewCommand(void)
{
if (coordinator_dynamic_view) {
if (!do_dynamic_view()) {
return 1;
}
} else {
do_view();
}
return 0;
}
static void DoReloadCommand(int *status, CtlOption *ctlCtx)
{
if (ctlCtx->guc.needDoGuc || ctlCtx->guc.nodeType != NODE_TYPE_UNDEF) {
ctlCtx->guc.gucCommand = RELOAD_CONF_COMMAND;
*status = DoGuc(ctlCtx);
} else {
if (g_clusterType == V3SingleInstCluster) {
write_runlog(LOG, "can't do cms reload, please add --agent or --server.\n");
return;
}
*status = DoReload();
}
}
static void CtlCommandProcessCore(int *status, CtlOption *ctlCtx)
{
switch (ctl_command) {
#ifdef ENABLE_MULTIPLE_NODES
case RESTART_COMMAND:
DoRestartCommand();
break;
#endif
case START_COMMAND:
*status = do_start();
break;
case CM_SWITCHOVER_COMMAND:
*status = DoSwitchover(ctlCtx);
break;
case CM_BUILD_COMMAND:
*status = DoBuild(ctlCtx);
break;
case STOP_COMMAND:
*status = DoStop();
break;
case CM_QUERY_COMMAND:
DoQueryCommand(status);
break;
case CM_SET_COMMAND:
DoSetCommand(status, ctlCtx);
break;
case CM_GET_COMMAND:
*status = do_get();
break;
case CM_VIEW_COMMAND:
*status = DoViewCommand();
break;
case CM_CHECK_COMMAND:
*status = do_check();
break;
case CM_SETMODE_COMMAND:
*status = do_setmode();
break;
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
case CM_HOTPATCH_COMMAND:
*status = do_hotpatch(hotpatch_exec, hotpatch_path);
break;
#endif
#ifdef ENABLE_MULTIPLE_NODES
case CM_DISABLE_COMMAND:
*status = do_disable_cn();
break;
#endif
#ifdef ENABLE_LIBPQ
case CM_FINISHREDO_COMMAND:
*status = do_finish_redo();
break;
case CM_DCF_SETRUNMODE_COMMAND:
*status = DoSetRunMode();
break;
case CM_DCF_CHANGEROLE_COMMAND:
*status = DoChangeRole(ctlCtx);
break;
case CM_DCF_CHANGEMEMBER_COMMAND:
*status = DoChangeMember(ctlCtx);
break;
#endif
case CM_RELOAD_COMMAND:
DoReloadCommand(status, ctlCtx);
break;
case CM_LIST_COMMAND:
ctlCtx->guc.gucCommand = LIST_CONF_COMMAND;
*status = DoGuc(ctlCtx);
break;
case CM_ENCRYPT_COMMAND:
*status = DoEncrypt(ctlCtx);
break;
case CM_SWITCH_COMMAND:
*status = DoSwitch(ctlCtx);
break;
case CM_RES_COMMAND:
*status = DoResCommand(&(ctlCtx->resOpt));
break;
case CM_SHOW_COMMAND:
*status = DoShowCommand();
break;
case CM_PAUSE_COMMAND:
*status = DoPause();
break;
case CM_RESUME_COMMAND:
*status = DoResume();
break;
case CM_RACK_COMMAND:
*status = DoRack();
break;
default:
write_runlog2(ERROR, errcode(ERRCODE_PARAMETER_FAILURE), errmsg("The option parameter is not specified."),
errdetail("N/A"), errmodule(MOD_CMCTL), errcause("The cmdline entered by the user is incorrect."),
erraction("Please check the cmdline entered by the user(%s).", g_cmdLine));
break;
}
}
bool CheckInputForSecurity(const char *input)
{
if (strstr(input, "%") == NULL) {
return true;
}
(void)printf("input constains invalid character.");
return false;
}
static bool RecordCommands(int argc, char **argv)
{
int rc;
char commands[MAXPGPATH] = "cm_ctl";
for (int i = 1; i < argc; i++) {
if (!CheckInputForSecurity(argv[i])) {
return false;
}
rc = strcat_s(commands, MAXPGPATH, " ");
securec_check_errno(rc, (void)rc);
rc = strcat_s(commands, MAXPGPATH, argv[i]);
securec_check_errno(rc, (void)rc);
}
write_runlog(DEBUG1, "ip: \"%s\", cmd: \"%s\". \n", g_currentNode->sshChannel[0], commands);
return true;
}
bool IsCmSharedStorageMode()
{
return g_isSharedStorageMode;
}
int main(int argc, char** argv)
{
uid_t uid = getuid();
if (uid == 0) {
(void)printf("current user is the root user (uid = 0), exit.\n");
return 1;
}
g_progname = "cm_ctl";
CheckArgcType(argc, argv);
static struct option longOptions[] = {
{"help", no_argument, NULL, '?'},
{"version", no_argument, NULL, 'V'},
{"log", required_argument, NULL, 'l'},
{"log_level", optional_argument, NULL, 1},
{"cm_arbitration_mode", optional_argument, NULL, 2},
{"cm_switchover_az_mode", optional_argument, NULL, 3},
{"cm_failover_delay_time", optional_argument, NULL, 4},
{"xmode", optional_argument, NULL, DCF_XMODE},
{"votenum", optional_argument, NULL, DCF_VOTE_NUM},
{"minorityAz", required_argument, NULL, MINORITY_AZ},
{"cmsPromoteMode", required_argument, NULL, CMS_P_MODE},
{"mode", required_argument, NULL, 'm'},
{"pgdata", required_argument, NULL, 'D'},
{"bin_name", required_argument, NULL, 'B'},
{"data_path", required_argument, NULL, 'T'},
#ifdef ENABLE_LIBPQ
{"role", required_argument, NULL, DCF_ROLE_MODE},
{"group", required_argument, NULL, DCF_GROUP},
{"priority", required_argument, NULL, DCF_PRIORITY},
#endif
{"node", required_argument, NULL, 'n'},
{"timeout", required_argument, NULL, 't'},
{"force", no_argument, NULL, 'f'},
#ifdef ENABLE_MULTIPLE_NODES
{"logic_name", required_argument, NULL, 'L'},
#endif
#if ((defined(ENABLE_MULTIPLE_NODES)) || (defined(ENABLE_PRIVATEGAUSS)))
{"hotpatch", required_argument, NULL, 'h'},
#endif
{"agent", no_argument, NULL, CM_AGENT_MODE},
{"server", no_argument, NULL, CM_SERVER_MODE},
{"ddb_type", optional_argument, NULL, CM_SWITCH_DDB},
{"commit", no_argument, NULL, CM_SWITCH_COMMIT},
{"rollback", no_argument, NULL, CM_SWITCH_ROLLBACK},
{"param", no_argument, NULL, CM_SET_PARAM},
{"add", no_argument, NULL, RES_ADD},
{"edit", no_argument, NULL, RES_EDIT},
{"del", no_argument, NULL, RES_DEL},
{"check", no_argument, NULL, RES_CHECK},
{"list", no_argument, NULL, RES_LIST},
{"res_name", required_argument, NULL, RES_NAME_INPUT},
{"res_attr", required_argument, NULL, RES_ATTR_INPUT},
{"add_inst", required_argument, NULL, RES_ADD_INST_INPUT},
{"del_inst", required_argument, NULL, RES_DEL_INST_INPUT},
{"edit_inst", required_argument, NULL, RES_EDIT_INST_INPUT},
{"inst_attr", required_argument, NULL, RES_INST_ATTR_INPUT},
{"list_inst", no_argument, NULL, RES_LIST_INST_INPUT},
{NULL, 0, NULL, 0}
};
int optionIndex;
int c;
int status = 0;
bool set_data_path = false;
CtlOption ctlCtx;
InitCtlOptionParams(&ctlCtx);
(void)pthread_mutex_init(&g_cmEnvLock, NULL);
int err_no = MakeupCmdline(argc, argv);
if (err_no == CM_EXIT) {
exit(1);
}
init_ctl_global_variable();
setup_signal_handle(SIGPIPE, SIG_IGN);
* save argv[0] so do_start() can look for the postmaster if necessary. we
* don't look for postmaster here because in many cases we won't need it.
*/
(void)umask(S_IRWXG | S_IRWXO);
logicClusterList lcList = {0};
set_cm_read_flag(true);
if (read_config_file_check() != 0) {
exit(-1);
}
(void)read_logic_cluster_name(g_logicClusterListPath, lcList, &err_no);
if (CmSSlConfigInit(true) != 0) {
write_runlog(ERROR, "CmSSlConfigInit init failed.\n");
exit(-1);
}
CtlDccCommand(argc, argv);
if (!RecordCommands(argc, argv)) {
exit(-1);
}
* 'Action' can be before or after args so loop over both. Some
* getopt_long() implementations will reorder argv[] to place all flags
* first (GNU?), but we don't rely on it. Our /port version doesn't do
* that.
*/
optind = 1;
vector<int> actionOptionsCode;
int lengthLongOptions = sizeof (longOptions)/sizeof (longOptions[0]);
while (optind < argc) {
while ((c = getopt_long(argc, argv, g_allowedOptions, longOptions, &optionIndex)) != -1) {
actionOptionsCode.push_back(c);
ParseCmdArgsCore(c, &set_data_path, &ctlCtx);
}
if (GetCtlCommand(argc, argv) == CM_ERROR) {
exit(1);
}
if (CheckActionOptionMatches(ctl_command, actionOptionsCode, longOptions, lengthLongOptions) == CM_ERROR) {
exit(1);
}
}
SetCommonDataPath(set_data_path, &ctlCtx);
CtlCheckComandType();
CtlCheckOther(&ctlCtx);
CtlCommandProcessCore(&status, &ctlCtx);
g_execute_cmctl_success = true;
ReleaseResource();
exit(status);
}