/* $Id: //depot/tools/main/performance/perfstat_cluster/src/perfstat.cpp#57 $ */ #include #include #include //#include bool signalReceived = false; int sigCount = 1; const int totalLoginAttempt = 3; static bool bNodeEntered = false; #ifndef WIN32 static struct termios default_stty, stty; #endif perfstat* perfstat :: perfInstance = NULL; perfstat* perfstat :: getPerfInstance() { if(perfInstance == NULL) { perfInstance = new perfstat(); } return perfInstance; } class perfstat::fatalPerfstat: public std::exception { virtual const char* what() const throw() { return "Fatal perfstat exception encountered"; } }; void perfstat::runPerfstat(int ac, char* av[]) { vector sysShellPasswd; time_t perfstatStartTime; time(&perfstatStartTime); connectionStatus = false; #ifndef WIN32 //get the default TTY attributes if (tcgetattr (STDIN_FILENO , &default_stty) != 0) { //do nothing } #endif commonOutputHandle = new outputHandler(); cliHandle = new CLIHandler(); //parse cli options cliHandle->collectCLIOptions(ac, av, commonOutputHandle); //load preset file presetHandle.loadPresetFile(cliHandle, commonOutputHandle); if(signalReceived) return; /* * Multiple cluster support. Set the connection status to false */ if(cliHandle->getClusterIP().size() && !(cliHandle->getFilerMode()).compare("10-mode")) { clusterConnectionStatus = vector(cliHandle->getClusterIP().size(), false); clusterConnectionHandle = vector(cliHandle->getClusterIP().size(), nullptr); } else { clusterConnectionStatus.push_back(false); clusterConnectionHandle.push_back(nullptr); } // Getting the Nodes from the CLI in case of 7-Mode if((cliHandle->getFilerMode()).compare("10-mode")) { nodeIPaddress = cliHandle->getNodeIPs(); for(int i = 0; i < nodeIPaddress.size(); ++i) { legacyFlags[nodeIPaddress[i]] = cliHandle->getLegacyMode(); } string temp = "Total number of controllers are: " + boost::lexical_cast((int)nodeIPaddress.size()); if((int)nodeIPaddress.size() ==0) { temp.append(" Exiting...\n"); commonOutputHandle->writeDataToLogFile("ERROR", temp); exit(0); } else { commonOutputHandle->writeDataToLogFile("INFO", temp); cliHandle->setNodeIPs(nodeIPaddress); } } /* if(!(cliHandle->getFilerMode()).compare("10-mode")) { if(cliHandle->getMccFlag() && (cliHandle->getClusterIP().size() > 1)) { commonOutputHandle->writeDataToLogFile("Error", "perfstat don't support multiple clusters management IPs with MCC enabled"); exit(0); } } */ // Check whether to run in Legacy Mode or not ? setupSSHKeys(&sysShellPasswd); if(signalReceived) { return; } //get all the nodes in the cluster //we gather system shell info only for 10-mode if(!(cliHandle->getFilerMode()).compare("10-mode")) { /* commonOutputHandle->writeDataToLogFile("INFO", "Gathering Metro cluster information from cluster management interface."); if (cliHandle->getMccFlag()) { string cmetroCluster; cmetroCluster = getMetroClusterInfo(); } */ commonOutputHandle->writeDataToLogFile("INFO", "Gathering node information from cluster management interface."); if(cliHandle->getNodeIPs().size() == 0) { nodeIPaddress = requestClusterInfo(); } else { nodeIPaddress = cliHandle->getNodeIPs(); } //setupSystemShell(""); string temp = "Total number of cluster nodes are: " + boost::lexical_cast((int)nodeIPaddress.size()); if((int)nodeIPaddress.size() == 0) { temp.append(" Exiting...\n"); commonOutputHandle->writeDataToLogFile("ERROR", temp); exit(0); } else { commonOutputHandle->writeDataToLogFile("INFO", temp); } } if(connectionStatus) { //(*connectionHandle).disconnectToFiler(); //delete connectionHandle; //connectionHandle = NULL; if (cliHandle->getClusterIP().size() > 0) { for(int i = 0; i < cliHandle->getClusterIP().size(); i++) { if (clusterConnectionStatus[i]) { (*clusterConnectionHandle[i]).disconnectToFiler(); } delete clusterConnectionHandle[i]; //clusterConnectionHandle[i] = NULL; } } else { (*connectionHandle).disconnectToFiler(); delete connectionHandle; connectionStatus = false; clusterConnectionStatus[0] = false; } } //add all node IPs in a vector if(signalReceived) { return; } if(nodePrompts.size() == 0) { for(int i=0; i<(int)nodeIPaddress.size(); i++) { nodePrompts.push_back(""); } } else { for(int i=1; i<(int)nodeIPaddress.size(); i++) { nodePrompts.push_back(""); } } //if(cliHandle->getNodeIPs().size() == 0) //we gather system shell password only for 10-mode if(!(cliHandle->getFilerMode()).compare("10-mode")) { string tmpPasswd = sysShellPasswd[0]; for(int i=0; i<(int)nodeIPaddress.size(); i++) { sysShellPasswd.push_back(tmpPasswd); } cliHandle->setNodeIPs(nodeIPaddress); } else { //For 7-mode, we dont require systemshell password so keep it NULL string for compatibility sake // The following piece of code should be commented so as to support systemshell commands in 7-mode /* for(int i=0; i<(int)nodeIPaddress.size(); i++) { sysShellPasswd.push_back(" "); } */ } // Just to ensure that Legacy Flag is false for C-Mode if((cliHandle->getFilerMode()).compare("10-mode") == 0) { for(int nIndex = 0; nIndex < nodeIPaddress.size(); ++nIndex) { legacyFlags[nodeIPaddress[nIndex]] = false; } } threadHandle = new threadHandler(presetHandle, cliHandle, commonOutputHandle, nodeIPaddress); threadHandle->startThreadHandler(nodeIPaddress, nodePrompts, sysShellPasswd, cliHandle->getMaxRunTime(), legacyFlags); delete threadHandle; threadHandle = NULL; if(!cliHandle->getSSHKeyProvidedFlag() && (cliHandle->getFilerMode()).compare("10-mode") == 0) { //commonOutputHandle->writeDataToLogFile("INFO", "Removing SSH Keys from controller.."); //Lets revert back the original permission of the SSH private key generated by perfstat in case of '7-mode' in Linux flavour #ifndef WIN32 if((cliHandle->getFilerMode()).compare("10-mode")) { string tmpSSHPrivKeyPath; tmpSSHPrivKeyPath = cliHandle->getSSHPrivateKeyPath(); string permChangeComm; permChangeComm = "/bin/chmod 0644 "; permChangeComm = permChangeComm + tmpSSHPrivKeyPath; std::system(permChangeComm.c_str()); } #endif if (!CLIHandler::getCleanUpFlag()) commonOutputHandle->writeDataToLogFile("INFO", "Provide Clean-Up flag in the CLI to remove SSH keys and perfstat user from the controller."); else cleanupSSHKeys(); commonOutputHandle->writeDataToLogFile("INFO", "Removing perfstat user and SSH keys from the controller."); } string zippingInfo = "Zipping up data into "; zippingInfo += cliHandle->getOutputFileName(); #ifdef WIN32 zippingInfo += ".zip"; #else zippingInfo += ".tar and "; string tarGZ = cliHandle->getOutputFileName(); tarGZ += ".tar.gz"; zippingInfo += tarGZ; #endif commonOutputHandle->writeDataToLogFile("INFO", zippingInfo); time_t perfstatEndTime; time(&perfstatEndTime); string data="--- EXE-TIME of : perfstat : "; data.append(boost::lexical_cast(perfstatEndTime - perfstatStartTime) + " seconds\n\n" ); commonOutputHandle->writeDataToLogFile("STATUS", data); (*commonOutputHandle).closeLogFile(); (*commonOutputHandle).generateArchiveFile(cliHandle->getOutputFileName()); } /* * This function check for the metro cluster availability. If avliable return the first node IP in the metro cluster. * I have not got any way to get the cluster management IP of the remote cluster directly. We got the name of the IP * and then use ping command to extract the IP of the node. * Second step would be connect to the metro cluster node and extract the cluster mgmt IP using command network interface show. */ string perfstat::getMetroClusterInfo(int clusterIndex) { string metroClusterNodesIP = string(); string command = "cluster peer show -fields remote-cluster-nodes"; (*clusterConnectionHandle[clusterIndex]).sendCommandToFiler(command); string output = (*clusterConnectionHandle[clusterIndex]).readResponseFromFiler(); if (output.find("There are no entries matching your query.") != string::npos) { commonOutputHandle->writeDataToLogFile("STATUS", "Failed to get Metro Cluster Information\n"); return metroClusterNodesIP; } typedef boost::tokenizer > tokenizer; boost::char_separator nodesep("\n ,"); tokenizer tokens(output, nodesep); for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); tok_iter++) { if (distance(tokens.begin(), tok_iter) == 12) { metroClusterNodesIP = *tok_iter; break; } } command = "ping -show-detail -count 1 -node local -destination " + metroClusterNodesIP; (*clusterConnectionHandle[clusterIndex]).sendCommandToFiler(command); output = (*clusterConnectionHandle[clusterIndex]).readResponseFromFiler(); if (output.find("ping: cannot resolve") != string::npos) { commonOutputHandle->writeDataToLogFile("WARNING", "Failed to get the Metro cluster Mgmt IP\n"); commonOutputHandle->writeDataToLogFile("WARNING", "Perfstat can be rerun with Site A and Site B cluster Mgmt IPs\n"); return string(); } boost::char_separator IPsep("()"); tokenizer IPtokens(output, IPsep); for (tokenizer::iterator tok_iter = IPtokens.begin(); tok_iter != IPtokens.end(); tok_iter++) { if (distance(IPtokens.begin(), tok_iter) == 1) { metroClusterNodesIP = *tok_iter; break; } } //tempNodes = parseNodeIPs(output); //for(vector::iterator j = tempNodes.begin(); j != tempNodes.end(); ++j) //clusterNodes.push_back(*j); //clusterNodes.push_back(parseNodeIPs(output)); //cliHandle->setNodeIPs(clusterNodes, i); //clusterNodes.clear(); /* } else { commonOutputHandle->writeDataToLogFile("Metro ERROR", "Error while connecting to cluster interface. Exiting\n"); commonOutputHandle->writeDataToLogFile("Metro ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(0); } */ return metroClusterNodesIP; } vector perfstat::requestClusterInfo() { vector clusterNodes; vector tempNodes; for(int i = 0; i < cliHandle->getClusterIP().size(); i++) { if(!clusterConnectionStatus[i]) { connectionHandle = new connectionHandler(cliHandle->getSSHKey(), cliHandle->getClusterIP()[i], cliHandle->getRequestTimeoutSecs(), commonOutputHandle); connectionStatus = (*connectionHandle).connectToFiler(); clusterConnectionHandle[i] = connectionHandle; clusterConnectionStatus[i] = connectionStatus; } if(clusterConnectionStatus[i]) { string command = "network interface show -role node-mgmt -status-admin up -status-oper up -address-family " + cliHandle->getIPFamily(); // Not fixed BURT - 860197, Issue come after that BURT-889447. Logical interface for all nodes are same. //Need to look for mix IPV4 and IPV6 node configured //string command = "network interface show -role node-mgmt -status-admin up -status-oper up -address-family ipv4"; //(*connectionHandle).sendCommandToFiler(command); (*clusterConnectionHandle[i]).sendCommandToFiler(command); //string output = (*connectionHandle).readResponseFromFiler(); string output = (*clusterConnectionHandle[i]).readResponseFromFiler(); tempNodes = parseNodeIPs(output); for(vector::iterator j = tempNodes.begin(); j != tempNodes.end(); ++j) clusterNodes.push_back(*j); //clusterNodes.push_back(parseNodeIPs(output)); cliHandle->setNodeIPs(clusterNodes, i); //clusterNodes.clear(); } else { commonOutputHandle->writeDataToLogFile("ERROR", "Error while connecting to cluster interface. Exiting\n"); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(1); } } return clusterNodes; } vector perfstat::parseNodeIPs(string dataStr) { commonOutputHandle->writeDataToLogFile("INFO", "network interface show output:\n" + dataStr); vector nodeIPs; //Not fixed BURT - 860197, Issue come after that BURT-889447 /*Commenting out the code as we run command with -address-family ipv4 or ipv4. We can't trust on *logical Interface as it could be same for different nodes Even */ //string logicalInterface = string("-"); //string cLogicalInterface = string(); size_t start = 0; string strTemp; size_t end; int l = dataStr.length(); size_t found; do { end = dataStr.find("\n", start); strTemp = dataStr.substr(start, (end - start)); found = strTemp.find("----"); start = end + 1; }while(found==string::npos && end!=string::npos ); if(end==string::npos) { //did not get "------" line, means no data from network interface commonOutputHandle->writeDataToLogFile("ERROR", "Total number of nodes in cluster are : 0. Exiting ...\n"); exit(0); } end = dataStr.find("\n", start); typedef boost::tokenizer > tokenizer; boost::char_separator sep(" "); while (end != string::npos) { strTemp = dataStr.substr(start, (end - start)); //found=strTemp.find("mgmt1"); // BURT536089 size_t tmp_1 = 0,tmp_2 = 0; tmp_1 = strTemp.find("true"); tmp_2 = strTemp.find("false"); if(tmp_1 !=string::npos) { found = tmp_1; } else if(tmp_2 != string::npos) { found = tmp_2; } else { found = string::npos; } //Burt 664426 Perfstat disconnect ssh for high value of option t found=strTemp.find("/"); int index =0; if(found != string::npos) { tokenizer tokens(strTemp, sep); int token_size = 0; for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) { token_size++; } if(token_size > 1) { for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) { /* Same logical interface shouldn't be added twice. */ /* if(index == 0) { cLogicalInterface = *tok_iter; cLogicalInterface = cLogicalInterface.substr(0, cLogicalInterface.find("_inet6")); } */ if(index ==2) { /* If we have not processed the logical interface yet * We add the IP address into node IP and add current Logical * interface into logical interface string. */ //if (logicalInterface.find(cLogicalInterface) == string::npos) { string temp = *tok_iter; nodeIPs.push_back(temp.substr(0, temp.find("/"))); //logicalInterface += "-" + cLogicalInterface; //} } if(index == 3) { string temp = *tok_iter; boost::algorithm::trim(temp); temp.append("::*>"); nodePrompts.push_back(temp); } index = index +1; } } } start = end + 1; end = dataStr.find("\n", start); } return nodeIPs; } void perfstat::generateSSHKeys(vector * systemShellPasswd) { string nodePasswd = ""; string passPhraseStr = ""; string passPhraseStrChk = ""; connectionHandler* connectionH = NULL; vector sshKeys; // Initialized, not to break the current flow of the code sshKeys.push_back("public_key"); sshKeys.push_back("private_key"); bool bLegacy = cliHandle->getLegacyMode(); if(((cliHandle->getFilerMode()).compare("10-mode") == 0) || (((cliHandle->getFilerMode()).compare("10-mode") != 0) && (bLegacy == false))) { commonOutputHandle->writeDataToLogFile("INFO", "No perfstat SSH Keypair directory provided."); commonOutputHandle->writeDataToLogFile("INFO", "Creating new perfstat SSH Keypair."); commonOutputHandle->writeDataToLogFile("INFO", "Requesting SSH passphrase from user."); do { commonOutputHandle->writeDataToLogFile("INPUT", "Enter SSH passphrase(empty for no passphrase):"); passPhraseStr = maskPassword(); commonOutputHandle->writeDataToLogFile("INPUT", "Enter same passphrase again:"); passPhraseStrChk = maskPassword(); if(passPhraseStr.compare(passPhraseStrChk) != 0) { commonOutputHandle->writeDataToLogFile("ERROR", "Passphrase mismatch. Please try again ...."); } } while(passPhraseStr.compare(passPhraseStrChk) != 0); cliHandle->setSSHKeyPaths(); commonOutputHandle->writeDataToLogFile("INFO", "Please wait! generating perfstat SSH Key pairs."); connectionH = new connectionHandler("", cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle); sshKeys.clear(); sshKeys = connectionH->generateSSHKey(cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); if(sshKeys.size() < 2) { commonOutputHandle->writeDataToLogFile("ERROR", "SSH Key generation failed. Exiting\n"); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(0); } CkSshKey * sshkey = new CkSshKey(); connectionH->createAuthenticationKey(sshkey, cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); cliHandle->setSSHKey(sshkey); } if(cliHandle->getNodeIPs().size() == 0) { //we gather system shell info only for 10-mode if(!(cliHandle->getFilerMode()).compare("10-mode")) { if(cliHandle->getClusterIP().size() == 0) { commonOutputHandle->writeDataToLogFile("ERROR", "Cluster Interface name and nodes name both empty. Exiting\n"); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(1); } } //loginNGShell call for 'NULL' node name meant only for cluster mode because there it gets the //cluster IP with getClusterIP call if(!(cliHandle->getFilerMode()).compare("10-mode")){ loginNGShell("", sshKeys[1]); for(int i = 0; i < cliHandle->getClusterIP().size(); i++) { clusterConnectionHandle[i]->setSSHKey(cliHandle->getSSHKey()); /* * FS and Higher releases of ONTAP has system shell commands support from NGSH shell */ if(clusterConnectionHandle[i]->sendCommandToFiler("version")) { string output = clusterConnectionHandle[i]->readResponseFromFiler(); try { if (checkFSAndHigher(output)) { cliHandle->setSystemShellLoginFlag(false); } else { cliHandle->setSystemShellLoginFlag(true); } } catch (perfstat::fatalPerfstat &e) { closeConnections(clusterConnectionHandle, cliHandle); exit(1); } } //connectionHandle->setSSHKey(cliHandle->getSSHKey()); } //(*systemShellPasswd).push_back(setupSystemShell("")); if((cliHandle->getSystemShellExcludedFlag() == false && cliHandle->getSystemShellLoginFlag()) || cliHandle->isDiagPasswdProvided()) //second check for burt744483 { (*systemShellPasswd).push_back(setupSystemShell("")); } else { (*systemShellPasswd).push_back(""); } } else { // Added to support systemshell for 7mode } } else { vector nodesIP = cliHandle->getNodeIPs(); int ip =0; if(!(cliHandle->getFilerMode()).compare("10-mode")){ loginNGShell(nodesIP[ip], sshKeys[1]); if (connectionHandle->sendCommandToFiler("version")) { string output = (*connectionHandle).readResponseFromFiler(); try { if (checkFSAndHigher(output)) { cliHandle->setSystemShellLoginFlag(false); } else { cliHandle->setSystemShellLoginFlag(true); } } catch (perfstat::fatalPerfstat &e) { closeConnections(connectionHandle); exit(1); } } nodeIPaddress.push_back(nodesIP[ip]); nodePrompts.push_back(connectionHandle->getNodePrompt()); connectionHandle->setSSHKey(cliHandle->getSSHKey()); //check for systemshell login if((cliHandle->getSystemShellExcludedFlag() == false && cliHandle->getSystemShellLoginFlag()) || cliHandle->isDiagPasswdProvided()) { //second check for burt744483 (*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); } else { (*systemShellPasswd).push_back(""); } if (connectionStatus) { string command = "network interface show -role cluster-mgmt"; (*clusterConnectionHandle[ip]).sendCommandToFiler(command); string output = (*clusterConnectionHandle[ip]).readResponseFromFiler(); string clusterMgmtIP = parseNodeIPs(output)[ip]; if (clusterMgmtIP.empty()) { commonOutputHandle->writeDataToLogFile("WARNING", "Finding cluster-mgmt IP for the node failed."); /* We put node IP as a cluster-Mgmt IP */ clusterMgmtIP = nodesIP[ip]; } /* In-case of 10-mode we assume all the node IPs belong to one cluster only */ for (int i = 0; i < cliHandle->getNodeIPs().size(); i++) cliHandle->setNodeToClusterMap(nodesIP[i], clusterMgmtIP); } //reset the connection for other node connectionStatus = false; clusterConnectionStatus[ip] = false; } else { // This is for 7-Mode for(int ip=0; ip<(int)nodesIP.size(); ip++) { // If Legacy Mode is selected, check for the existence of "rsh" and then // provide the user the choice of using ssh.exe // Deprecated - if plink.exe is not supported //if(cliHandle->getLegacyMode() == true && cliHandle->getSSHFlag() == false) { if(cliHandle->getLegacyMode() == true ) { bool bRSHCheck = cliHandle->getNativeRshPresent();//checkRSH(nodesIP[ip]); // This is the case with rsh for Legacy Mode if(cliHandle->getSSHFlag() == false) { commonOutputHandle->writeDataToLogFile("INFO", nodesIP[ip], "Checking \"rsh\" connectivity..."); if(bRSHCheck == true) { legacyFlags[nodesIP[ip]] = true; (*systemShellPasswd).push_back(""); } else { commonOutputHandle->writeDataToLogFile("WARNING", "Native rsh binary (\"rsh\") does not exist on this host."); #ifdef WIN32 commonOutputHandle->writeDataToLogFile("STATUS", "Please setup \"openssh\" by following \"openssh_procedure.txt\" and re-run the command with -g option."); commonOutputHandle->writeDataToLogFile("STATUS", "Example: \"perfstat8.exe --verbose --nodes= --mode=\"7-mode\" -g --sshprivatekey-file=\"privatekey\" --LEGACY_MODE\" [OPTIONS]\n"); #else string info = "please try, \"rsh -l root " + nodesIP[ip] + " version \"\n"; commonOutputHandle->writeDataToLogFile("STATUS", info); #endif exit(0); } } // This is the case of --SSH provided. else { // If this is a linux host, just exit saying private key should accompany ssh #ifndef WIN32 if(cliHandle->getSSHKeyProvidedFlag() == false) { commonOutputHandle->writeDataToLogFile("WARNING", "Exiting now. Please re-run the perfstat with --SSH and --sshprivatekey-file options\n"); exit(0); } #else // There is no rsh.exe. so, will hang in that case //if(cliHandle->getOPenSSHFlag() == false) { // We should not be idle here. // We should exit from here as we can't proceeded. OpenSSH work in-conjunction with sshkeys only. commonOutputHandle->writeDataToLogFile("STATUS", "Please setup \"openssh\" by following \"openssh_procedure.txt\" and re-run the command with -g option."); commonOutputHandle->writeDataToLogFile("STATUS", "Example: \"perfstat8.exe --verbose --nodes= --mode=\"7-mode\" -g --sshprivatekey-file=\"privatekey\" --LEGACY_MODE\"\n"); exit(0); //} /* Deprecated from Perfstat v8.3 else { //loginNGShell(nodesIP[ip], sshKeys[1]); checkCreds(nodesIP[ip]); legacyFlags[nodesIP[ip]] = true; (*systemShellPasswd).push_back(""); } */ #endif } } else { loginNGShell(nodesIP[ip], sshKeys[1]); //nodeIPaddress.push_back(nodesIP[ip]); nodePrompts.push_back(connectionHandle->getNodePrompt()); connectionHandle->setSSHKey(cliHandle->getSSHKey()); // Added Not to allow system Shell password to be asked if --exclude="SHELL=SYSTEMSHELL" is used if(cliHandle->getSystemShellExcludedFlag() == false) { // Changed to check this only for LEGACY MODE bool isSystemShellPresent = false; if(isRunInLegacyMode(nodesIP[ip]) == false) { isSystemShellPresent = isSystemShellLocked(nodesIP[ip]); } if(isSystemShellPresent == true) { // Added to support systemshell support for 7-mode (*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); } else { (*systemShellPasswd).push_back(""); } } else { (*systemShellPasswd).push_back(""); } //check for systemshell login //we gather system shell info only for 10-mode. The only exception is sktrace collection. So lets collect the diag user credentials //if(!(cliHandle->getFilerMode()).compare("10-mode")){ //(*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); //} //Delete the connectionHandler object for each node as it will create problem later while creating the thread or individual nodes and executing commands if(connectionStatus) { if(isRunInLegacyMode(nodesIP[ip]) == false) { (*connectionHandle).disconnectToFiler(); } delete connectionHandle; connectionStatus = false; clusterConnectionStatus[0] = false; } } } } } delete connectionH; connectionH = NULL; } void perfstat::setupSSHKeys(vector * systemShellPasswd) { string nodePasswd= ""; //string ver = "version"; string sshPrivateKeyFilename = cliHandle->getSSHPrivateKeyPath(); string privkey; cliHandle->getSSHKeyProvidedFlag() ? (privkey = commonOutputHandle->readSSHKey(sshPrivateKeyFilename)):(privkey = string()); if(!cliHandle->getSSHKeyProvidedFlag() || privkey.empty()) { generateSSHKeys(systemShellPasswd); } else { commonOutputHandle->writeDataToLogFile("INFO", "Perfstat user should have Administrator privileges. Otherwise some command will fail or never return to perfstat"); bool bSSHKeyFlag = true; //handling if ssh-privkey file is provided at the command line string passPhraseStr=""; //Burt696005 start /** As there is no api provided by chilkat library to figure out well in advance if the private * key is passphrase protected or not. The crude way out is to check the following strings in the private key: * 1- OpenSSH generated keys with passphrase will have 'ENCRYPTED' string, alike the excerpt from a private key- * Proc-Type: 4,ENCRYPTED * 2- Puttygen generated keys will have 'Encryption' field whose value will be "none" in case of no passphrase * specified otherwise encypted value of passphrase */ //bool getPassphrase = false; if(strstr(sshPrivateKeyFilename.c_str(), ".ppk")) { if(!strstr(privkey.c_str(), "Encryption: none")) { if (cliHandle->getSSHPassPhraseFlag()) passPhraseStr = cliHandle->getSSHKeyPassPhrase(); //getPassphrase = true; } else { commonOutputHandle->writeDataToLogFile("ERROR", "SSH keys are encrypted. Please provide the passphrase to decode."); exit(1); } } else { if(strstr(privkey.c_str(), "ENCRYPTED")) { if (cliHandle->getSSHPassPhraseFlag()) { passPhraseStr = cliHandle->getSSHKeyPassPhrase(); //getPassphrase = true; } else { commonOutputHandle->writeDataToLogFile("ERROR", "SSH keys are encrypted. Please provide the passphrase to decode."); commonOutputHandle->writeDataToLogFile("INFO","Provide CLI options SSHKey-passPhrase="); exit(1); } } } /* if(getPassphrase) { commonOutputHandle->writeDataToLogFile("INFO", "Requesting SSH passphrase from user."); commonOutputHandle->writeDataToLogFile("INPUT", "Enter passphrase for SSH key:"); passPhraseStr= maskPassword(); } */ //Burt696005 end CkSshKey * sshkey = new CkSshKey(); commonOutputHandle->writeDataToLogFile("INFO", "Please wait! trying to authenticate using SSH Key pairs."); if(cliHandle->getNodeIPs().size() == 0) { //we gather system shell info only for 10-mode if(!(cliHandle->getFilerMode()).compare("10-mode")) { if(cliHandle->getClusterIP().size() == 0) { commonOutputHandle->writeDataToLogFile("ERROR", "Cluster Interface name and nodes name both empty. Exiting\n"); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat -h\" for details on options.\n"); exit(2); } } vector sshKeys; size_t ClusterIPSize = cliHandle->getClusterIP().size(); for(int i = 0; i < ClusterIPSize; i++) { clusterConnectionHandle[i] = new connectionHandler(cliHandle->getClusterIP()[i], cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle); if (i == 0) { connectionHandle = clusterConnectionHandle[i]; } //connectionHandle = new connectionHandler(cliHandle->getClusterIP()[0], //cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle); sshKeys = clusterConnectionHandle[i]->createAuthenticationKey(sshkey, cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); clusterConnectionHandle[i]->setSSHKey(sshkey); clusterConnectionStatus[i] = clusterConnectionHandle[i]->connectToFiler(); if (i == 0) { connectionStatus = clusterConnectionStatus[i]; if(connectionStatus && clusterConnectionHandle[i]->sendCommandToFiler("version")) { string output = clusterConnectionHandle[i]->readResponseFromFiler(); try { if (checkFSAndHigher(output)) { cliHandle->setSystemShellLoginFlag(false); } else { cliHandle->setSystemShellLoginFlag(true); } } catch (perfstat::fatalPerfstat &e) { closeConnections(clusterConnectionHandle, cliHandle); exit(1); } } } if(!clusterConnectionStatus[i]) { commonOutputHandle->writeDataToLogFile("ERROR", cliHandle->getClusterIP()[i], "Connection to the controller failed."); commonOutputHandle->writeDataToLogFile("INFO","Continue with other clusters if any"); clusterConnectionHandle[i]->disconnectToFiler(); delete clusterConnectionHandle[i]; erase_clusterConnectionHandle(i); cliHandle->erase_ClusterIP(i); //Reduce Clusters IP list by one. ClusterIPSize--; i--; continue; } else { //connectionHandle->connectToSystemShell(); //Commented for SSHkey authentication in cluster mode //(*systemShellPasswd).push_back(setupSystemShell(cliHandle->getClusterIP())); if((cliHandle->getSystemShellExcludedFlag() == false && cliHandle->getSystemShellLoginFlag()) || cliHandle->isDiagPasswdProvided()) { (*systemShellPasswd).push_back(setupSystemShell(cliHandle->getClusterIP()[i])); } else { (*systemShellPasswd).push_back(""); } } /* Multiple cluster management IPs not supported In-case MCC flag enabled*/ string metroClusterNodeIP = string(); if (cliHandle->getMccFlag() && clusterConnectionStatus[i]) { commonOutputHandle->writeDataToLogFile("STATUS", "Gathering Metro cluster information."); metroClusterNodeIP = getMetroClusterInfo(i); if(metroClusterNodeIP.size() == 0) { commonOutputHandle->writeDataToLogFile("WARNING", "Metro Cluster not found."); continue; } /* * Connect to metro Cluster nodeIP. Get the cluster management IP. * push the cluster IP into the clusterIPs. */ clusterConnectionHandle.push_back(new connectionHandler(metroClusterNodeIP, cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle)); sshKeys = clusterConnectionHandle[cliHandle->getClusterIP().size()]->createAuthenticationKey(sshkey, cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); clusterConnectionHandle[cliHandle->getClusterIP().size()]->setSSHKey(sshkey); clusterConnectionStatus.push_back(clusterConnectionHandle[cliHandle->getClusterIP().size()]->connectToFiler()); if (!clusterConnectionStatus[cliHandle->getClusterIP().size()]) { commonOutputHandle->writeDataToLogFile("WARNING", metroClusterNodeIP, "Metro Cluster node is not reachable"); delete clusterConnectionHandle[clusterConnectionHandle.size() - 1]; clusterConnectionHandle.pop_back(); clusterConnectionStatus.pop_back(); continue; } /* Metro node got connected. Extract the cluster mgmt IP */ string command = "network interface show -role cluster-mgmt -status-admin up -status-oper up"; (*clusterConnectionHandle[cliHandle->getClusterIP().size()]).sendCommandToFiler(command); string output = (*clusterConnectionHandle[cliHandle->getClusterIP().size()]).readResponseFromFiler(); /* Disconnect to the Metro cluster Node */ clusterConnectionHandle[cliHandle->getClusterIP().size()]->disconnectToFiler(); /* Set the Connection false */ clusterConnectionStatus[cliHandle->getClusterIP().size()] = false; /* * Push the Cluster management IP into the ClusterIPs vector in the end. * This will increare the size of the ClusterIPs vector. */ cliHandle->push_ClusterIP((parseNodeIPs(output))[0]); /* Connect to Metro cluster management IP */ clusterConnectionHandle[cliHandle->getClusterIP().size() - 1] = new connectionHandler( cliHandle->getClusterIP()[cliHandle->getClusterIP().size() - 1], cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle); sshKeys = clusterConnectionHandle[cliHandle->getClusterIP().size() - 1]->createAuthenticationKey(sshkey, cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); clusterConnectionHandle[cliHandle->getClusterIP().size() - 1]->setSSHKey(sshkey); clusterConnectionStatus[cliHandle->getClusterIP().size() - 1] = clusterConnectionHandle[cliHandle->getClusterIP().size() - 1]->connectToFiler(); if (!clusterConnectionStatus[cliHandle->getClusterIP().size() - 1]) { commonOutputHandle->writeDataToLogFile("WARNING", metroClusterNodeIP,"Metro Cluster management interface is not reachable"); cliHandle->pop_ClusterIP(); delete clusterConnectionHandle[clusterConnectionHandle.size() -1]; clusterConnectionHandle.pop_back(); clusterConnectionStatus.pop_back(); continue; } else { //connectionHandle->connectToSystemShell(); //Commented for SSHkey authentication in cluster mode //(*systemShellPasswd).push_back(setupSystemShell(cliHandle->getClusterIP())); if((cliHandle->getSystemShellExcludedFlag() == false && cliHandle->getSystemShellLoginFlag()) || cliHandle->isDiagPasswdProvided()) { //second check for burt744483) (*systemShellPasswd).push_back(setupSystemShell(cliHandle->getClusterIP()[cliHandle->getClusterIP().size() - 1])); } else { (*systemShellPasswd).push_back(""); } } } } if (ClusterIPSize == 0) { commonOutputHandle->writeDataToLogFile("STATUS", "Failed to connect with the controllers."); exit(0); } } else { vector nodesIP = cliHandle->getNodeIPs(); vector nodeStat; int ip =0; if(!(cliHandle->getFilerMode()).compare("10-mode")) { connectionHandle = new connectionHandler(nodesIP[ip], cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle); vector sshKeys = connectionHandle->createAuthenticationKey(sshkey, cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); connectionHandle->setSSHKey(sshkey); connectionStatus = connectionHandle->connectToFiler(); clusterConnectionHandle[ip] = connectionHandle; if (connectionStatus) { string command = "network interface show -role cluster-mgmt"; (*clusterConnectionHandle[ip]).sendCommandToFiler(command); string output = (*clusterConnectionHandle[ip]).readResponseFromFiler(); string clusterMgmtIP = parseNodeIPs(output)[ip]; if (clusterMgmtIP.empty()) { commonOutputHandle->writeDataToLogFile("WARNING", "Finding cluster-mgmt IP for the node failed."); /* We put node IP as a cluster-Mgmt IP */ clusterMgmtIP = nodesIP[ip]; } if(clusterConnectionHandle[ip]->sendCommandToFiler("version")) { string output = (*clusterConnectionHandle[ip]).readResponseFromFiler(); try { if (checkFSAndHigher(output)) { cliHandle->setSystemShellLoginFlag(false); } else { cliHandle->setSystemShellLoginFlag(true); } } catch (perfstat::fatalPerfstat &e) { closeConnections(clusterConnectionHandle[ip]); exit(1); } } /* In-case of 10-mode we assume all the node IPs belong to one cluster only */ for (int i = 0; i < cliHandle->getNodeIPs().size(); i++) cliHandle->setNodeToClusterMap(nodesIP[i], clusterMgmtIP); } if(!connectionStatus) { delete connectionHandle; connectionHandle = nullptr; clusterConnectionHandle[ip] = nullptr; loginNGShell(nodesIP[ip], ""); nodeIPaddress.push_back(nodesIP[ip]); nodePrompts.push_back(connectionHandle->getNodePrompt()); //connectionStatus = connectionHandle->sendCommandToFiler(ver); if(clusterConnectionHandle[ip]->sendCommandToFiler("version")) { try { if (checkFSAndHigher((*clusterConnectionHandle[ip]).readResponseFromFiler())) { cliHandle->setSystemShellLoginFlag(false); } else { cliHandle->setSystemShellLoginFlag(true); } } catch (perfstat::fatalPerfstat &e) { closeConnections(clusterConnectionHandle[ip]); exit(1); } string command = "network interface show -role cluster-mgmt"; (*clusterConnectionHandle[ip]).sendCommandToFiler(command); string output = (*clusterConnectionHandle[ip]).readResponseFromFiler(); string clusterMgmtIP = parseNodeIPs(output)[ip]; if (clusterMgmtIP.empty()) { commonOutputHandle->writeDataToLogFile("WARNING", "Finding cluster-mgmt IP for the node failed."); /* We put node IP as a cluster-Mgmt IP */ clusterMgmtIP = nodesIP[ip]; } /* In-case of 10-mode we assume all the node IPs belong to one cluster only */ for (int i = 0; i < cliHandle->getNodeIPs().size(); i++) cliHandle->setNodeToClusterMap(nodesIP[i], clusterMgmtIP); } //reset the connection for other node connectionStatus = false; clusterConnectionStatus[ip] = false; } else { nodeIPaddress.push_back(nodesIP[ip]); nodePrompts.push_back(connectionHandle->getNodePrompt()); } //(*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); if((cliHandle->getSystemShellExcludedFlag() == false && cliHandle->getSystemShellLoginFlag()) || cliHandle->isDiagPasswdProvided()) { //second check for burt744483 (*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); } else { (*systemShellPasswd).push_back(""); } } else { for(int ip=0; ip<(int)nodesIP.size(); ip++) { connectionHandle = new connectionHandler(nodesIP[ip], cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle); if(isRunInLegacyMode(nodesIP[ip]) == false) { vector sshKeys = connectionHandle->createAuthenticationKey(sshkey, cliHandle->getSSHPrivateKeyPath(), cliHandle->getSSHPublicKeyPath(), passPhraseStr); connectionHandle->setSSHKey(sshkey); } // connectionStatus = connectionHandle->connectToFiler(); // Removing SFTP dependency // This code is duplicated...Need to seperate it. // No need of this check....As we are already into the code of SSHKeyProvided == true if(isRunInLegacyMode(nodesIP[ip]) == false) { if(cliHandle->getOPenSSHFlag() == true) { bool bOpenSSHCheck = checkOpenSSHKey(nodesIP[ip]); if(bOpenSSHCheck == true) { legacyFlags[nodesIP[ip]] = true; cliHandle->setLegacyMode(true); connectionStatus = true; } else { //commonOutputHandle->writeDataToLogFile("ERROR", "Exiting, as OpenSSH key is not correct\n"); // REVIEW_COMMENTS commonOutputHandle->writeDataToLogFile("ERROR", nodesIP[ip], "The supplied ssh privatekey is not matching with the publickey on the controller. Exiting!!"); commonOutputHandle->writeDataToLogFile("STATUS", nodesIP[ip], "Please verify if ssh is working by running the following command."); commonOutputHandle->writeDataToLogFile("STATUS", nodesIP[ip], "ssh.exe -i -l \"date\""); commonOutputHandle->writeDataToLogFile("INFO", nodesIP[ip], "expected output is system date should be printed.\n"); exit(0); } } else { if((cliHandle->getFilerMode()).compare("10-mode") != 0 && cliHandle->getSSHKeyProvidedFlag() == false) { vector filerInfo = cliHandle->getFilerCreds(nodesIP[ip]); if(filerInfo.size() == 2) { connectionStatus = connectionHandle->connectToFiler(filerInfo[1]); } else{ commonOutputHandle->writeDataToLogFile("ERROR", "Failed to collect correct creds\n"); } } else { connectionStatus = connectionHandle->connectToFiler(); } } } else { bool bOpenSSHCheck = true; if(cliHandle->getOPenSSHFlag() == true) { bOpenSSHCheck = checkOpenSSHKey(nodesIP[ip]); cliHandle->setLegacyMode(true); } else { if(cliHandle->getSSHKeyProvidedFlag() == true) { if(cliHandle->getSSHFlag() == true) { bOpenSSHCheck = checkOpenSSHKey(nodesIP[ip], true); } else { #ifndef WIN32 commonOutputHandle->writeDataToLogFile("ERROR", "Exiting. Please provide the --sshprivatekey-file along with --SSH option\n"); #else commonOutputHandle->writeDataToLogFile("ERROR", "Exiting. Please provide the --sshprivate-key along with --SSH or -g option\n"); #endif bOpenSSHCheck = false; } } } if(bOpenSSHCheck == true) { legacyFlags[nodesIP[ip]] = true; connectionStatus = true; } else { string smdToTest = "Unable to use key file " + cliHandle->getSSHPrivateKeyPath(); smdToTest = smdToTest + ". Exiting."; commonOutputHandle->writeDataToLogFile("ERROR", nodesIP[ip], smdToTest); if(cliHandle->getOPenSSHFlag() == true) { //smdToTest = "ssh.exe -o BatchMode=yes -2 -ax -i -l \"version\""; smdToTest = "ssh.exe -o BatchMode=yes -2 -ax -i -o -l \"version\""; } else { #ifdef WIN32 /* Deprecated plink.exe It has to be OpenSSH only*/ //smdToTest = "plink.exe -ssh -x -a -batch -i -l \"version\""; smdToTest = "ssh.exe -o BatchMode=yes -2 -ax -i -o -l \"version\""; #else smdToTest = "ssh -o BatchMode=yes -2 -ax -i -n -l \"version\""; #endif } smdToTest = "Please try, " + smdToTest; smdToTest = smdToTest + "\n"; commonOutputHandle->writeDataToLogFile("STATUS", smdToTest); exit(0); } connectionStatus = true; } if(!connectionStatus) { bool bLegacy = false; if(cliHandle->getSSHKeyProvidedFlag() == true) { int nAttempt = 0; bool bPermission = false; bool statusFlag = false; while((nAttempt < 2) && (statusFlag == false)) { if(connectionHandle->getSSHErrorCode() == PERFSTAT_SSH_ERRORS_SESSION_ALREADY_EXISTS) { if(bPermission == false) { bLegacy = askForLegacyMode(nodesIP[ip]); legacyFlags[nodesIP[ip]] = bLegacy; if(bLegacy == true) { legacyFlags[nodesIP[ip]] = true; #ifdef WIN32 bool bRsh = cliHandle->getNativeRshPresent(); if(bRsh == true) { // If SSH is used then check if plink is present or not ? if(cliHandle->getSSHFlag() == true && cliHandle->getOPenSSHFlag() == false) { /* Deprecated from Perfstat 8.3 release bool bfileExists = commonOutputHandle->fileExists("plink.exe"); if(bfileExists == false) { bfileExists = commonOutputHandle->fileExists("plink"); } if(bfileExists == false) { */ commonOutputHandle->writeDataToLogFile("STATUS", "Please setup \"openssh\" by following \"openssh_procedure.txt\" and re-run the command with -g option."); //commonOutputHandle->writeDataToLogFile("STATUS", "Please copy the plink.exe in the same directory where perfstat8 binary is present and re-run the perfstat test.\n"); exit(0); //} } commonOutputHandle->writeDataToLogFile("STATUS", "Running perfstat in LEGACY MODE. This run wouldn't collect Systemshell data and SKTRACE data"); //cliHandle->setLegacyMode(true); connectionStatus = true; connectionHandle->disconnectToFiler(); statusFlag = true; break; } else { if(cliHandle->getSSHFlag() == false) { commonOutputHandle->writeDataToLogFile("STATUS", "Native rsh binary (\"rsh.exe\") does not exist on this host."); } commonOutputHandle->writeDataToLogFile("STATUS", "Please setup \"openssh\" by following \"openssh_procedure.txt\" and re-run the command with -g option."); commonOutputHandle->writeDataToLogFile("STATUS", "Example: \"perfstat8.exe --verbose --nodes= --mode=\"7-mode\" -g --sshprivatekey-file=\"privatekey\" --LEGACY_MODE\"\n"); exit(0); } #else connectionStatus = true; connectionHandle->disconnectToFiler(); statusFlag = true; break; #endif } bPermission = true; } if(bPermission == true) { commonOutputHandle->writeDataToLogFile("INFO", "Please close the session that is already open."); statusFlag = connectionHandle->connectToFiler(); // Burt that crashes while running in current mode with SSH and Key and refused to switch to Legacy mode and re-try closing the opened SSH/Telnet session BURT_611981 connectionStatus = statusFlag; } } else if(connectionHandle->getSSHErrorCode() == PERFSTAT_SSH_ERRORS_WRONG_PASSWORD) { string smdToTest = "Unable to use key file " + cliHandle->getSSHPrivateKeyPath(); smdToTest = smdToTest + ". Exiting."; commonOutputHandle->writeDataToLogFile("ERROR", nodesIP[ip], smdToTest); #ifdef WIN32 smdToTest = smdToTest = "ssh.exe -o BatchMode=yes -2 -ax -i -o -l \"version\"";; //smdToTest = "plink.exe -ssh -x -a -batch -i -l \"version\""; #else smdToTest = "ssh -o BatchMode=yes -2 -ax -i -n -l \"version\""; #endif smdToTest = smdToTest + "\n"; commonOutputHandle->writeDataToLogFile("INFO", nodesIP[ip], "please try, " + smdToTest); exit(0); } else { // Future Reference statusFlag = false; break; } ++nAttempt; } if(statusFlag == false) { commonOutputHandle->writeDataToLogFile("INFO", "Exiting, Not successful in Entering NGShell.\n"); exit(0); } if(isRunInLegacyMode(nodesIP[ip]) == false) { //nodeIPaddress.push_back(nodesIP[ip]); // Commented JUNE_11 nodePrompts.push_back(connectionHandle->getNodePrompt()); } } } else { //nodeIPaddress.push_back(nodesIP[ip]); nodePrompts.push_back(connectionHandle->getNodePrompt()); } // Added to not allow system Shell password to be asked if --exclude="SHELL=SYSTEMSHELL" is used if(cliHandle->getSystemShellExcludedFlag() == false) { bool isSystemShellPresent = false; if(isRunInLegacyMode(nodesIP[ip]) == false) { isSystemShellPresent = isSystemShellLocked(nodesIP[ip]); } if(isSystemShellPresent == true) { (*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); } else { (*systemShellPasswd).push_back(""); } } else { (*systemShellPasswd).push_back(""); } //check for systemshell login //we gather system shell info only for 10-mode. Exceptional case would be sktrace collection so Lets collect the diag user credentials //By the way you are already in 7-mode ;-) why have you put this condition here ??? if(!(cliHandle->getFilerMode()).compare("10-mode")){ //(*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); if(cliHandle->getSystemShellExcludedFlag() == false || cliHandle->isDiagPasswdProvided()) { (*systemShellPasswd).push_back(setupSystemShell(nodesIP[ip])); } else { (*systemShellPasswd).push_back(""); } } //Delete the connectionHandler object for each node as it will create problem later while creating the thread or individual nodes and executing commands if(connectionStatus) { if(isRunInLegacyMode(nodesIP[ip]) == false) { (*connectionHandle).disconnectToFiler(); } delete connectionHandle; connectionStatus = false; clusterConnectionStatus[0] = false; } } } } if(cliHandle->getSSHKeyProvidedFlag() == true && bSSHKeyFlag == true) { cliHandle->setSSHKey(sshkey); } } } bool perfstat::setupSSHKeyOnFiler(string nodeip, string key, string nodePasswd, int i) { if((cliHandle->getFilerMode()).compare("10-mode") == 0) { if(key.empty()) { string publicKeyfile; commonOutputHandle->writeDataToLogFile("INPUT", "Enter SSH public key filename."); #ifdef WIN32 cin >> publicKeyfile; #else publicKeyfile = readPublicKey(); #endif cliHandle->setSSHPublicKeyPath(publicKeyfile); key = commonOutputHandle->readSSHKey(publicKeyfile); } commonOutputHandle->writeDataToLogFile("INFO", "Please wait! sending SSH Key to controllers."); } //Sumit if(!connectionStatus) { if(!clusterConnectionStatus[i]) { /* * Changed the constructor to take CLIHandler reference. * clusterConnectionHandle is in sync with ClusterIPs. Add any Ips in the end of the vector. * All the clusterConnectionHandle handles freed in end of function runPerfstat(). */ clusterConnectionHandle[i] = new connectionHandler(cliHandle->getSSHKey(), nodeip, cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle ); clusterConnectionStatus[i] = clusterConnectionHandle[i]->connectToFiler(nodePasswd); if (i == 0 ) {//&& clusterConnectionStatus[i]) { connectionHandle = clusterConnectionHandle[i]; connectionStatus = clusterConnectionStatus[i]; } } //if(connectionStatus) { if(clusterConnectionStatus[i]) { if(!(cliHandle->getFilerMode()).compare("10-mode")) { commonOutputHandle->writeDataToLogFile("INFO", "Please wait! Creating Perfstat user with Administrator privilege"); string command = "security login create -username perfstat -application ssh -authmethod publickey"; //(*connectionHandle).sendCommandToFiler(command); (*clusterConnectionHandle[i]).sendCommandToFiler(command); //string output = (*connectionHandle).readResponseFromFiler(); string output = (*clusterConnectionHandle[i]).readResponseFromFiler(); command = "security login publickey create -username perfstat -index 1 -publickey \"" + key; command.append("\" -comment \"Public key for Perfstat\""); //(*connectionHandle).sendCommandToFiler(command); (*clusterConnectionHandle[i]).sendCommandToFiler(command); //output = (*connectionHandle).readResponseFromFiler(); output = (*clusterConnectionHandle[i]).readResponseFromFiler(); if(!output.empty() && output.length() != 0) { size_t found = output.find("Local unit offline"); if(found != string::npos) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to setup public key on controller. Exiting\n"); exit(0); } found = output.find("duplicate"); if(found != string::npos) { //need to delete the alreday existing entry string command = "security login publickey delete -username perfstat -index 1"; //(*connectionHandle).sendCommandToFiler(command); (*clusterConnectionHandle[i]).sendCommandToFiler(command); //output = (*connectionHandle).readResponseFromFiler(); output = (*clusterConnectionHandle[i]).readResponseFromFiler(); command = "security login publickey create -username perfstat -index 1 -publickey \"" + key; command.append("\" -comment \"Public key for Perfstat\""); //(*connectionHandle).sendCommandToFiler(command); (*clusterConnectionHandle[i]).sendCommandToFiler(command); //output = (*connectionHandle).readResponseFromFiler(); output = (*clusterConnectionHandle[i]).readResponseFromFiler(); } } } else { // For future Reference } } else { return false; } return true; } void perfstat::cleanupSSHKeys() { //we gather system shell info only for 10-mode if(!(cliHandle->getFilerMode()).compare("10-mode")) { if(cliHandle->getClusterIP().size()!=0) { connectionHandle = new connectionHandler(cliHandle->getSSHKey(), cliHandle->getClusterIP()[0], cliHandle->getRequestTimeoutSecs(), commonOutputHandle,cliHandle); //added cliHandle connectionStatus = connectionHandle->connectToFiler(); if(connectionStatus) { string command = "security login publickey delete -username perfstat -index 1"; (*connectionHandle).sendCommandToFiler(command); string output = (*connectionHandle).readResponseFromFiler(); } (*connectionHandle).disconnectToFiler(); delete connectionHandle; } else { vector nodesIP = cliHandle->getNodeIPs(); int ip =0; //for(int ip=0; ip<(int)nodeIPaddress.size(); ip++) { connectionHandle = new connectionHandler(cliHandle->getSSHKey(), nodeIPaddress[ip], cliHandle->getRequestTimeoutSecs(), commonOutputHandle,cliHandle); //added clihandle connectionStatus = connectionHandle->connectToFiler(); if(connectionStatus){ string command = "security login publickey delete -username perfstat -index 1"; (*connectionHandle).sendCommandToFiler(command); string output = (*connectionHandle).readResponseFromFiler(); } (*connectionHandle).disconnectToFiler(); delete connectionHandle; } } } else { // For Future Reference } } void perfstat::getAllFilesFromFilers( vector shpasswd) { vector nodesIP; if(!(cliHandle->getFilerMode()).compare("10-mode")) { nodesIP = nodeIPaddress; } else { nodesIP = cliHandle->getNodeIPs(); } int ip =0; for(int ip=0; ip<(int)nodesIP.size(); ip++) { connectionHandle = new connectionHandler(cliHandle->getSSHKey(), nodesIP[ip], cliHandle->getRequestTimeoutSecs(), commonOutputHandle, cliHandle ); //added the clihandle constructor // Removing SFTP dependency if((cliHandle->getFilerMode()).compare("10-mode") != 0 && cliHandle->getSSHKeyProvidedFlag() == false) { vector filerInfo = cliHandle->getFilerCreds(nodesIP[ip]); if(filerInfo.size() == 2) { connectionStatus = connectionHandle->connectToFiler(filerInfo[1]); } else{ commonOutputHandle->writeDataToLogFile("ERROR", "Failed to collect correct creds\n"); } } else { connectionStatus = connectionHandle->connectToFiler(); } if(connectionStatus) { //string command = "security login publickey delete -username perfstat -index 1"; //(*connectionHandle).sendCommandToFiler(command); //string output = (*connectionHandle).readResponseFromFiler(); //Now retrieve the files from the controller which got collected due to RAStrace or gmon profiling // RASTRACE, PROFILE, BACKUP and SKTRACE collection if(cliHandle->getProfileFlag() || cliHandle->getModuleInstFlag() || cliHandle->getSKTraceFlag() || cliHandle->getBackUpLogFlag()) { commonOutputHandle->writeDataToLogFile("INFO", "Downloading files from controller. This may take some time...\n"); #ifdef WIN32 bool status = (*connectionHandle).getFilesFromFilersAsSftp(nodesIP[ip],cliHandle->getSSHKey(),shpasswd[ip]); if( status != true) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to retrieve file from the controller. Exiting\n"); } #else bool status = (*connectionHandle).getFilesFromFilersAsSftp(nodesIP[ip],cliHandle->getSSHKey(),shpasswd[ip]); if( status != true) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to retrieve file from the controller. Exiting\n"); } #endif } } else { commonOutputHandle->writeDataToLogFile("ERROR", nodesIP[ip], "Failed to connect inside getAllFilesFromFilers"); } (*connectionHandle).disconnectToFiler(); delete connectionHandle; } } void perfstat::loginNGShell(string node, string SSHKey) { string inputStr; string userName; int attemptCount = 0; bool status = false; bool legacyTest = false; int i = 0; int ConnectfailCount = cliHandle->getClusterIP().size(); while(attemptCount < totalLoginAttempt && !status) { string tmp; if(isRunInLegacyMode(node) == false) { commonOutputHandle->writeDataToLogFile("INFO", "Setting up controller for SSH Public Key."); } if(node.compare("")==0) { if(!(cliHandle->getFilerMode()).compare("10-mode")) { userName = "Enter username with cluster admin privileges: "; commonOutputHandle->writeDataToLogFile("INPUT", userName); cin>>userName; cin.ignore(); tmp = "Enter passwd(user:" + userName + "):"; //tmp = "Enter controller passwd(user:admin):"; } else { tmp = "Enter controller passwd(user:root):"; } } else { if(!(cliHandle->getFilerMode()).compare("10-mode")) { userName = "Enter username with cluster admin privilege from (node:" + node + "):"; commonOutputHandle->writeDataToLogFile("INPUT", userName); cin>>userName; cin.ignore(); //tmp = "Enter ngshell(" + node + ") passwd(user:admin):"; tmp = "Enter (node:" + node + ") passwd(user:" + userName + "):"; } else { userName = "Enter nodeshell(" + node + ") username : "; commonOutputHandle->writeDataToLogFile("INPUT", userName); cin>>userName; cin.ignore(); //ignore the '\n' character because it will make maskPassword function not accept the passwd tmp = "Enter nodeshell(" + node + ") passwd(user:" + userName + "):"; } } commonOutputHandle->writeDataToLogFile("INPUT", tmp); inputStr = maskPassword(); commonOutputHandle->writeDataToLogFile("INFO", "Authenticating.."); if(node.compare("")==0) { size_t ClusterIPSize = cliHandle->getClusterIP().size(); for(i; i < ClusterIPSize; i++) { string metroClusterNodeIP = string(); cliHandle->setFilerCreds(cliHandle->getClusterIP()[i], userName, inputStr); status = setupSSHKeyOnFiler(cliHandle->getClusterIP()[i], SSHKey, inputStr, i); if (clusterConnectionHandle[i]->getConnectResponseCode() == 401) { //commonOutputHandle->writeDataToLogFile("STATUS", cliHandle->getClusterIP()[i], "Authentication failed with the controller."); //attemptCount++; break; } if (status) attemptCount = 0; /* Multiple cluster management IPs not supported In-case MCC flag enabled */ /* * Code has support for multiple management IP for Metro cluster but never tested * We had a check for multiple cluster-IPs in-case metro cluster and error out */ if (cliHandle->getMccFlag() && status) { commonOutputHandle->writeDataToLogFile("STATUS", "Gathering Metro cluster information from (Site A) cluster management interface."); metroClusterNodeIP = getMetroClusterInfo(i); if(metroClusterNodeIP.size() == 0) { commonOutputHandle->writeDataToLogFile("INFO", "Metro Cluster not found."); continue; } /* Set the metro cluster node connection status and clusterConnectionHandle */ clusterConnectionStatus.push_back(false); clusterConnectionHandle.push_back(nullptr); /* * Connect to metro Cluster nodeIP. Get the cluster management IP. * push the cluster IP into the clusterIPs. */ cliHandle->setFilerCreds(metroClusterNodeIP, userName, inputStr); status = setupSSHKeyOnFiler(metroClusterNodeIP, SSHKey, inputStr, cliHandle->getClusterIP().size()); if (!status) { commonOutputHandle->writeDataToLogFile("INFO", "Metro Cluster node is not reachable"); delete clusterConnectionHandle[clusterConnectionHandle.size() - 1]; clusterConnectionHandle.pop_back(); clusterConnectionStatus.pop_back(); continue; } /* For succesful connection. Extract the cluster mgmt IP */ string command = "network interface show -role cluster-mgmt -status-admin up -status-oper up"; (*clusterConnectionHandle[cliHandle->getClusterIP().size()]).sendCommandToFiler(command); string output = (*clusterConnectionHandle[cliHandle->getClusterIP().size()]).readResponseFromFiler(); /* Disconnect to the Metro cluster Node */ clusterConnectionHandle[cliHandle->getClusterIP().size()]->disconnectToFiler(); /* Set the Connection false */ clusterConnectionStatus[cliHandle->getClusterIP().size()] = false; /* * Push the Cluster management IP into the ClusterIPs vector in the end. * This will increare the give of the ClusterIPs vector. */ cliHandle->push_ClusterIP((parseNodeIPs(output))[0]); /* Connect to Metro cluster management IP */ status = setupSSHKeyOnFiler(cliHandle->getClusterIP()[cliHandle->getClusterIP().size() - 1], SSHKey, inputStr, (cliHandle->getClusterIP().size() -1)); if (!status) { commonOutputHandle->writeDataToLogFile("INFO", "Metro Cluster management interface is not reachable"); cliHandle->pop_ClusterIP(); delete clusterConnectionHandle[clusterConnectionHandle.size() - 1]; clusterConnectionHandle.pop_back(); clusterConnectionStatus.pop_back(); continue; } } /* * If we failed to connect to the cluster. We take out * the cluster from the list without failing on * other clusters */ if(!status) { commonOutputHandle->writeDataToLogFile("STATUS",cliHandle->getClusterIP()[i],"Failed to connect to the controller."); commonOutputHandle->writeDataToLogFile("INFO", "Same credentials should be set for all the controllers"); commonOutputHandle->writeDataToLogFile("INFO","Continue with other clusters if any"); clusterConnectionHandle[i]->disconnectToFiler(); cliHandle->erase_ClusterIP(i); delete clusterConnectionHandle[i]; erase_clusterConnectionHandle(i); ClusterIPSize--; i--; ConnectfailCount--; continue; } } } else { if((cliHandle->getFilerMode()).compare("10-mode")) { cliHandle->setFilerCreds(node, userName, inputStr); } else { cliHandle->setFilerCreds(node, userName, inputStr); } status = setupSSHKeyOnFiler(node, SSHKey, inputStr); } if(!status) { if(!(cliHandle->getFilerMode()).compare("10-mode")) { if(ConnectfailCount == 0) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to connect with controllers. Exiting.."); commonOutputHandle->writeDataToLogFile("ERROR", "Please try ssh -l controller name from host machine"); exit(0); } commonOutputHandle->writeDataToLogFile("ERROR", "Incorrect ngshell passwd. Please try again...\n"); } else { // Test whether the failure is because of already existing session or not ? PERFSTAT_SSH_ERRORS sshConnectivityError = connectionHandle->getSSHErrorCode(); if(sshConnectivityError == PERFSTAT_SSH_ERRORS_SESSION_ALREADY_EXISTS) { if(cliHandle->getLegacyMode() == true){ legacyFlags[node] = true; status = true; connectionHandle->disconnectToFiler(); break; } else { //string info = "Attempt : " + boost::lexical_cast(attemptCount + 1); //info += "failed\n"; //commonOutputHandle->writeDataToLogFile("ERROR", info); //commonOutputHandle->writeDataToLogFile("ERROR", "controller already has an established connection \n"); // Ask for the LEGACY at the first time if(legacyTest == false) { bool blegacy = askForLegacyMode(node); legacyFlags[node] = blegacy; if(blegacy == true) { legacyFlags[node] = true; #ifdef WIN32 /* if(cliHandle->getSSHFlag() == false) { commonOutputHandle->writeDataToLogFile("INFO", "Checking \"rsh\" connectivity..."); } bool bRsh = checkRSH(node); */ bool bRsh = cliHandle->getNativeRshPresent(); if(bRsh == true) { if(cliHandle->getSSHFlag() == true && cliHandle->getOPenSSHFlag() == false) { /* bool bfileExists = commonOutputHandle->fileExists("plink.exe"); if(bfileExists == false) { bfileExists = commonOutputHandle->fileExists("plink"); } if(bfileExists == false) { */ commonOutputHandle->writeDataToLogFile("STATUS", "Please setup \"openssh\" by following \"openssh_procedure.txt\" and re-run the command with -g option."); //commonOutputHandle->writeDataToLogFile("STATUS", "Please copy the plink.exe in the same directory where perfstat8 binary is present and re-run perfstat test.\n"); exit(0); //} } commonOutputHandle->writeDataToLogFile("STATUS", "Running perfstat in LEGACY MODE. This run wouldn't collect Systemshell data and SKTRACE data" ); //cliHandle->setLegacyMode(true); status = true; connectionHandle->disconnectToFiler(); break; } else { if(cliHandle->getSSHFlag() == false) { commonOutputHandle->writeDataToLogFile("STATUS", "Native rsh binary (\"rsh.exe\") does not exist on this host"); } commonOutputHandle->writeDataToLogFile("STATUS", "Please setup \"openssh\" by following \"openssh_procedure.txt\" and re-run the command with -g option."); commonOutputHandle->writeDataToLogFile("STATUS", "Example: \"perfstat8.exe --verbose --nodes= --mode=\"7-mode\" -g --sshprivatekey-file=\"privatekey\" --LEGACY_MODE\"\n"); exit(0); } #else status = true; connectionHandle->disconnectToFiler(); break; #endif } } else { commonOutputHandle->writeDataToLogFile("ERROR", "Please, \"CLOSE\" the sessions that are open and RETRY."); if(legacyTest == true) { attemptCount = totalLoginAttempt; } } legacyTest = true; } } else if(sshConnectivityError == PERFSTAT_SSH_ERRORS_WRONG_PASSWORD) { commonOutputHandle->writeDataToLogFile("ERROR", "Incorrect nodeshell passwd. Please try again..."); } else { // Other cases } } } else { commonOutputHandle->writeDataToLogFile("INFO", "Successful login"); if ((cliHandle->getFilerMode()).compare("10-mode") && cliHandle->getLegacyMode() == true) { connectionHandle->disconnectToFiler(); } } attemptCount++; } if(!status) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to login to ngshell. Exiting.."); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(0); } } bool perfstat :: checkRSH(const string& node) { bool bRes = true; string user = cliHandle->getFilerLoginUser(); string testCmd = ""; #ifdef WIN32 testCmd = "rsh.exe >output_test_RSH 2>output_test_RSH_error"; _flushall(); #else testCmd = "rsh >output_test_RSH 2>output_test_RSH_error"; #endif int res = std::system(testCmd.c_str()); string out = commonOutputHandle->readFromFile("output_test_RSH_error"); if(!out.empty()) { if(out.find("is not recognized as an internal or external command") != string::npos) { bRes = false; } else { bRes = true; } } else { bRes = false; } remove("output_test_RSH"); remove("output_test_RSH_error"); return bRes; } string perfstat::setupSystemShell(string node) { // Check if LEGACY MODE is true or not ? // If LEGACY MODE is set to true then just return. if(isRunInLegacyMode(node) == true) { return ""; } string inputStr = ""; int attemptCount = 0; bool status = false; int index = 0; if((cliHandle->getFilerMode()).compare("10-mode") == 0) { index = 1; } bool success = false; // Check whether the diag password is provided in the CLI Options if(cliHandle->isDiagPasswdProvided() == true) { inputStr = cliHandle->getSystemShellPasswd(node, index); success = true; } /* * This is new code added in 8.3 . Perfstat get call from UI we don't want * blocking calls in perfstat. In-case diag password not provided we processed * without system shell commands execution. */ else { commonOutputHandle->writeDataToLogFile("INFO", "To execute system shell commands, please provide CLI option --diag-passwd=\"diag-password\"\n"); commonOutputHandle->writeDataToConsole("INFO", node, "System shell commands excluded\n"); cliHandle->setSystemShellExcludedFlag(true); return ""; } while(attemptCount < totalLoginAttempt && !status) { string tmp; if(!success) { if(node.compare("") == 0) { tmp = "Enter system shell passwd(user:diag):"; } else { tmp = "Enter systemshell(" + node + ") passwd(user:diag):"; } commonOutputHandle->writeDataToLogFile("INPUT", tmp); inputStr = maskPassword(); cout << "Please wait. Authenticating.."; } else { #ifndef WIN32 // work around, need to figure out sleep(3); #endif } status = connectionHandle->loginSystemShell(inputStr); if(!status) { commonOutputHandle->writeDataToLogFile("ERROR", "Incorrect systemshell passwd."); commonOutputHandle->writeDataToLogFile("INFO", "Excluding system Shell commands"); success = false; cliHandle->setSystemShellExcludedFlag(true); return ""; if(attemptCount == 1) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to login to systemshell. Exiting.."); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(0); } attemptCount++; } else { commonOutputHandle->writeDataToLogFile("INFO", "Successful systemshell login"); } } if(!status) { commonOutputHandle->writeDataToLogFile("ERROR", "Failed to login to systemshell. Exiting.."); commonOutputHandle->writeDataToLogFile("ERROR", "Please run \"perfstat8.exe -h\" for details on options.\n"); exit(0); } return inputStr; } #ifdef WIN32 string perfstat::maskPassword() { string password; int c; do { c = getch(); switch (c) { case 0: getch(); break; case '\b': if (password.length()) { cout << "\b \b"; password.erase( password.end() -1 ); } break; default: if (isalnum( c ) || ispunct( c )) { cout << ""; password.push_back( c ); } } } while (c != '\r'); return password; } #else string perfstat::readPublicKey() { char pubkey[128]; int i=0; char ch; fflush(stdin); fflush(stdout); memset(&pubkey,0,128); //suppress_echo(); while ((ch = getchar()) != '\n') { if (i > 127) break; else pubkey[i++] = ch; } fflush(stdin); fflush(stdout); //make_echo(); return pubkey; } string perfstat::maskPassword() { char password[128]; int i=0; char ch; fflush(stdin); fflush(stdout); memset(&password,0,128); suppress_echo(); while ((ch = getchar()) != '\n') { if (i > 127) break; else password[i++] = ch; } fflush(stdin); fflush(stdout); make_echo(); return password; } #if 0 int perfstat::setDefaultTTY() { int fd; fd = open(tty_path(), O_RDWR); if (fd < 0) return -1; if (ioctl(fd, TCGETS, &default_stty) < 0) return -2; close(fd); return 0; } #endif int perfstat::suppress_echo() { /* int fd; fd = open(tty_path(), O_RDWR); if (fd < 0) return -1; if (ioctl(fd, TCGETS, &default_stty) < 0) return -2; bcopy(&default_stty, &stty, sizeof(struct termios)); stty.c_lflag &= ~(ECHO | CLOCAL); // suppress echo if (ioctl(fd, TCSETS, &stty) < 0) return -3; close(fd); */ /* Turn echoing off and fail if we can't. */ if (tcgetattr (STDIN_FILENO , &default_stty) != 0) return -1; bcopy(&default_stty, &stty, sizeof(struct termios)); stty.c_lflag &= ~(ECHO | CLOCAL); // suppress echo if (tcsetattr (STDIN_FILENO , TCSANOW, &stty) != 0) return -3; return 0; } int perfstat::make_echo() { /* int fd; fd = open(tty_path(), O_RDWR); if (fd < 0) return -1; // just return to our previous tty state if (ioctl(fd, TCSETS, &default_stty) < 0) return -2; close(fd); */ // just return to our previous tty state if( tcsetattr (STDIN_FILENO , TCSANOW, &default_stty) !=0 ) return -2; return 0; } char* perfstat::tty_path() { static char buf[128]; memset(&buf,0,128); if (readlink("/proc/self/fd/0", buf,128) == -1) return NULL; return buf; } #endif #ifndef WIN32 void signalHandler(int sig) { string inputStr; if(sig == 2) //SIGINT { if(sigCount <= 1) { cout << "Received CTRL-C Interrupt.. Do you want to exit(Y/N):"; cin >> inputStr; if(inputStr.compare("y") == 0 || inputStr.compare("Y") == 0) { signalReceived = true; sigCount = sigCount + 1; cout << "Preparing for graceful exit please wait...\n"; } else signalReceived = false; } else { sigCount = sigCount + 1; cout << "Already received CTRL-C Interrupt..Exiting right now...\n"; if(bNodeEntered == false) { exit(0); } } } else { sigCount = sigCount + 1; signalReceived = true; } // just return to our previous tty state if( tcsetattr (STDIN_FILENO , TCSANOW, &default_stty) !=0 ) return; #if 0 int fd; static char buf[128]; memset(&buf,0,128); if (readlink("/proc/self/fd/0", buf,128) == -1) return; fd = open(buf, O_RDWR); if (fd < 0) return; if (ioctl(fd, TCSETS, &default_stty) < 0) return; close(fd); #endif } #endif #ifdef WIN32 void winSignalHandler(int sig) { string inputStr; sigCount = sigCount + 1; signalReceived = true; } BOOL WINAPI signalhandler(DWORD dwCtrlType) { if (dwCtrlType == CTRL_C_EVENT){ string inputStr; if(sigCount <= 1) { cout << "Received CTRL-C Interrupt.. Do you want to exit(Y/N):"; cin >> inputStr; if(inputStr.compare("y") == 0 || inputStr.compare("Y") == 0) { signalReceived = true; sigCount = sigCount + 1; cout << "Preparing for graceful exit please wait...\n"; cout << "Please make sure syslog.conf entry where ONTAP running in 7-mode..\n"; } else signalReceived = false; } else { sigCount = sigCount + 1; cout << "Already received CTRL-C Interrupt..Exiting right now...\n"; cout << "Please make sure syslog.conf entry where ONTAP running in 7-mode..\n"; cout << "Remove existing syslog.conf(rm /etc/syslog.conf) and move syslog.conf_orig(mv /etc/syslog.conf_orig /etc/syslog.conf) to syslog.conf if exist."; if(bNodeEntered == false) { exit(0); } } } else { sigCount = sigCount + 1; signalReceived = true; } return TRUE; } #endif #ifndef DTEST int main(int ac, char* av[]) { #ifndef WIN32 (void) signal(SIGINT, signalHandler); (void) signal(SIGABRT, signalHandler); #else SetConsoleCtrlHandler(signalhandler,TRUE); (void) signal(SIGABRT, winSignalHandler); #endif // perfstat perf; // perf.runPerfstat(ac, av); (perfstat::getPerfInstance())->runPerfstat(ac, av);; //getchar(); } #endif bool perfstat::signalStatus() { return signalReceived; } int perfstat :: getSigCount() { return sigCount; } void perfstat :: setNodeEntered(bool bEntered) { bNodeEntered = bEntered; } bool perfstat :: isSystemShellLocked(string nodeIP) { bool cmodeFlag = true; bool systemShellPresentFlag = false; if((cliHandle->getFilerMode()).compare("10-mode")) { cmodeFlag = false; } string command = ""; if(cmodeFlag == false) { command = "priv set -q diag;useradmin diaguser show"; if(connectionHandle != NULL) { connectionHandle->sendCommandToFiler(command); string output = connectionHandle->readResponseFromFiler(); if(!output.empty()) { vector data = cliHandle->tokenizeString(output, "\n"); for(vector::iterator it = data.begin(); it < data.end(); ++it) { string info = *it; if(info.find("Invalid option 'diaguser'") != string::npos) { systemShellPresentFlag = false; break; } else { int position = 0; if((position = info.find("Locked:")) != string::npos) { position = position + 8; string value = info.substr(position,2); std::transform(value.begin(), value.end(), value.begin(), (int(*)(int))std::toupper); if(value.compare("NO") == 0) { systemShellPresentFlag = true; } break; } } } } } } return systemShellPresentFlag; } void perfstat :: cleanLogoutSystemShell() { if((cliHandle->getFilerMode()).compare("10-mode") != 0) { int numOfNodes = (cliHandle->getNodeIPs()).size(); if(threadHandle != NULL) { node* nodeList = threadHandle->getNodes(); for(int nodeIndex = 0; nodeIndex < numOfNodes; ++nodeIndex) { if(isRunInLegacyMode((cliHandle->getNodeIPs())[nodeIndex]) == false) { if(nodeList[nodeIndex].is7ModeSystemShell() == true) { (nodeList[nodeIndex].getConnectionHandle())->logoutSystemShell(); (nodeList[nodeIndex].getConnectionHandle())->disconnectToFiler(); } } } } } } bool perfstat :: askForLegacyMode(const string& nodeIP) { string choice = ""; bool bChoice = false; commonOutputHandle->writeDataToLogFile("STATUS", nodeIP, "There is an active SSH/Telnet session already connected to the Node."); commonOutputHandle->writeDataToLogFile("STATUS", "Switch to LEGACY MODE(Excludes systemshell commands and SKTrace )"); //cin >> choice; //cin.ignore(); //std::transform(choice.begin(), choice.end(), choice.begin(), (int(*)(int))std::toupper); //if(choice.compare("Y") == 0 || choice.compare("YES") == 0) { bChoice = true; //} //else { //commonOutputHandle->writeDataToLogFile("STATUS", "Perfstat will continue to run in the normal mode."); //commonOutputHandle->writeDataToLogFile("STATUS", "So, please make sure all the existing telnet/ssh sessions if any with the NODE are closed"); //bChoice = false; //} return bChoice; } bool perfstat :: isRunInLegacyMode(string ip) { bool bLegacyRun = false; if((cliHandle->getFilerMode()).compare("10-mode") == 0 || ((cliHandle->getFilerMode()).compare("10-mode") != 0 && legacyFlags[ip] == false)) { //((cliHandle->getFilerMode()).compare("10-mode") != 0 && cliHandle->getLegacyMode() == false)) { bLegacyRun = false; } else { bLegacyRun = true; } return bLegacyRun; } bool perfstat :: checkOpenSSHKey(string nodeIP, bool bPlink) { string strPrivKeyPath = cliHandle->getSSHPrivateKeyPath(); string strSSHKnownHostsFilePath = cliHandle->getSSHKnownHostsFilePath(); string user = cliHandle->getFilerLoginUser(); int nAttempt = 0; bool bRes = true; string cmd = ""; #ifdef WIN32 /* bplink always false in-case Perfstat v8.3 */ //if(bPlink == false) { string temp = "known_hosts"; if(strSSHKnownHostsFilePath.empty()) { strSSHKnownHostsFilePath = strPrivKeyPath; strSSHKnownHostsFilePath.replace(strSSHKnownHostsFilePath.find_last_of("\\") + 1, temp.length(), temp); } strSSHKnownHostsFilePath.insert(0,"UserKnownHostsFile="); cmd = "ssh.exe -o BatchMode=yes -2 -ax -i \"" + strPrivKeyPath + "\"" + " -o " + "\"" + strSSHKnownHostsFilePath + "\"" + " "; cmd = cmd + " -l " + user; cmd = cmd + " " + nodeIP + " "; //cmd = cmd + "\"version\""; //cout << cmd; //} //else { /* #ifdef WIN32 cmd= "plink.exe -ssh -x -a -batch -i \"" + strPrivKeyPath + "\""; cmd = cmd + " -l " + user; cmd = cmd + " " + nodeIP + " "; */ #else //ssh -o BatchMode=yes -2 -ax -i 1234 10.61.76.195 -n -l root "version" cmd = "ssh -o BatchMode=yes -2 -ax -i \"" + strPrivKeyPath + "\" "; cmd = cmd + nodeIP; cmd = cmd + " -n -l " + user; cmd = cmd + " "; #endif cmd = cmd + "\"version\""; //} string outPath = cliHandle->getOutputFileName(); string outPathResult = outPath + "/output_test_connectivity"; string outPathError = outPath + "/output_test_connectivity_error"; cmd = cmd + " >" + outPathResult; cmd = cmd + " 2>" + outPathError; #ifdef WIN32 _flushall(); #endif std::system(cmd.c_str()); string out = commonOutputHandle->readFromFile(outPathResult); if(!out.empty()) { if (out.find("NetApp") == string::npos && out.find("ONTAP") == string::npos){ bRes = false; } else { bRes = true; } } else { commonOutputHandle->writeDataToLogFile("INFO", "Cannot open the Test File\n"); bRes = false; } remove(outPathResult.c_str()); remove(outPathError.c_str()); return bRes; } void perfstat::checkCreds(const string& ip) { string inputStr; string userName; int attemptCount = 0; bool status = false; bool legacyTest = false; while(attemptCount < totalLoginAttempt && !status) { userName = "Enter nodeshell(" + ip + ") username : "; commonOutputHandle->writeDataToLogFile("INPUT", userName); cin>>userName; cin.ignore(); string tmp = "Enter nodeshell(" + ip + ") passwd(user:" + userName + "):"; commonOutputHandle->writeDataToLogFile("INPUT", tmp); inputStr = maskPassword(); string rshCommand = "plink.exe -ssh -x -a -batch -pw "; rshCommand = rshCommand + inputStr + " -l " + userName; rshCommand = rshCommand + " " + ip; rshCommand = rshCommand + " \"version\" >ssh_test_output_perfstat 2>ssh_test_output_perfstat_error"; int ret = std::system(rshCommand.c_str()); if(ret == 0) { string output = commonOutputHandle->readFromFile("ssh_test_output_perfstat"); if(output.find("NetApp") == string::npos && output.find("ONTAP") == string::npos) { status = false; } else { status = true; } } else { status = false; } if(status == false) { ++attemptCount; commonOutputHandle->writeDataToLogFile("INFO", "Unsuccessful password authentication\n"); } else { commonOutputHandle->writeDataToLogFile("INFO", "Successful password authentication\n"); cliHandle->setFilerCreds(ip, userName, inputStr); } std::remove("ssh_test_output_perfstat"); std::remove("ssh_test_output_perfstat_error"); } if(status == false) { commonOutputHandle->writeDataToLogFile("INFO", "Exiting, As the username and password Authentication failed\n"); exit(0); } } // Closes just one connection void perfstat::closeConnections(connectionHandler* conn) { conn->disconnectToFiler(); } // Closes all connections in the vector void perfstat::closeConnections(vector conns, CLIHandler* cliHandle) { for(int i = 0; i < cliHandle->getClusterIP().size(); i++) { conns[i]->disconnectToFiler(); } } bool perfstat::checkFSAndHigher(string output) { string ver = string(); //output = "version: Command not found" if (output.find("Command not found") != string::npos) { commonOutputHandle->writeDataToLogFile("ERROR", "unable to determine ONTAP version."); commonOutputHandle->writeDataToLogFile("ERROR", "Please make sure to specify a user with correct privileges (cluster admin or 7mode node admin) during startup."); cout << endl; throw fatalPerfstat(); } //output = "NetApp Release 8.3.1: Thu Nov 06 09:10:55 UTC 2014"; typedef boost::tokenizer > tokenizer; boost::char_separator sep(" :"); tokenizer tokens(output, sep); for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); tok_iter++) { if (distance(tokens.begin(), tok_iter) == 2) { ver = *tok_iter; if (ver.find("__") != string::npos) { ver = cliHandle->tokenizeString(ver, "__")[1]; } break; } } int minor = 0; int major = boost::lexical_cast(cliHandle->tokenizeString(ver, ".")[0]); string minor_s = boost::lexical_cast(cliHandle->tokenizeString(ver, ".")[1]); for(std::string::iterator it=minor_s.begin(); it != minor_s.end(); it++) if (std::isdigit(*it)) { minor = minor*10 + (*it - '0'); } else { break; } if (major >= 8 && minor >= 3) return true; else return false; } string perfstat::convert_EPOCH_to_gmtime(time_t epoch) { #ifdef __linux__ char buffer[80]; strftime(buffer,80," [ %a %b %d %H:%M:%S GMT %Y]",std::gmtime(&epoch)); return string(buffer); #else std::stringstream ss; ss << " [" << std::put_time(std::gmtime(&epoch), "%a %b %d %H:%M:%S GMT %Y") << ']'; return ss.str(); #endif } void perfstat::erase_clusterConnectionHandle(int pos) { clusterConnectionHandle.erase(clusterConnectionHandle.begin() + pos); }