sequentialScriptRunner.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. // all scripts run with base directory as frontend
  3. include_once '../util/Logger.php';
  4. include_once '../conf/Config.inc';
  5. include_once 'localDirs.php';
  6. include_once "../util/lock.php";
  7. include_once '../db/HMCDBAccessor.php';
  8. include_once "../util/HMCTxnUtils.php";
  9. include_once "commandUtils.php";
  10. include_once '../util/util.php';
  11. // this script will write to TransactionStatus table the following:
  12. // 1. txn-id -> describes state sshable, discoverable, bootstrapable
  13. // 2. status_info blob -> specific errors for the state
  14. // initial setup
  15. $logger = new HMCLogger("sequentialScriptExecutor");
  16. $dbHandle = new HMCDBAccessor($GLOBALS["DB_PATH"]);
  17. function updateProgressForStage($clusterName, $rootTxnId, $orchestratorTxnId,
  18. $mySubTxnId, $operationName, $numTotalNodes) {
  19. global $logger, $dbHandle, $stagesInfo;
  20. $clusterDir = getClusterDir($clusterName);
  21. $commandOutputDir = $clusterDir . $operationName . "/";
  22. $numNodesFailed = 0;
  23. $numNodesSucceeded = 0;
  24. $additionalInfo = array();
  25. $foundDir = FALSE;
  26. if (is_dir($commandOutputDir) && $dirHandle = opendir($commandOutputDir)) {
  27. if (!$foundDir) {
  28. $logger->log_debug($commandOutputDir . " exists finally ");
  29. }
  30. $foundDir = TRUE;
  31. while (false !== ($entry = readdir($dirHandle))) {
  32. if ($entry == "." || $entry == "..") {
  33. continue;
  34. }
  35. // Only consider .out files
  36. if(!preg_match("/.out/", $entry)) {
  37. continue;
  38. }
  39. $nodeName = basename($entry, ".out");
  40. $doneFile = $commandOutputDir . $nodeName . ".done";
  41. if (file_exists($doneFile)) {
  42. // Read the contents of the done-file
  43. $doneFileContents = file_get_contents($doneFile);
  44. if (trim($doneFileContents) == "0") {
  45. $numNodesSucceeded++;
  46. $additionalInfo[$nodeName] = "Successful with no errors.";
  47. } else {
  48. $numNodesFailed++;
  49. // Let's read the errors
  50. $errorFile = $commandOutputDir . $nodeName . ".err";
  51. $errorFileContents = file_get_contents($errorFile);
  52. $additionalInfo[$nodeName] = "Failed. Reason: $errorFileContents";
  53. }
  54. }
  55. }
  56. } else {
  57. $logger->log_debug( $commandOutputDir . " still doesn't exist");
  58. }
  59. $logger->log_debug(" Current operation is $operationName and commandOutput dir: $commandOutputDir");
  60. $logger->log_debug(" total nodes: $numTotalNodes, succeeded: $numNodesSucceeded, failed: $numNodesFailed");
  61. $progressState = generateNodeActionProgress($numTotalNodes, $numNodesSucceeded, $numNodesFailed, "succeeded");
  62. $logger->log_debug(" Current progressState is ".$progressState);
  63. $state = json_encode($additionalInfo); $description = $stagesInfo[$operationName]["description"]; $progress = $progressState; $subTxnType = "";
  64. $subTransactionReturnValue = $dbHandle->insertOrUpdateSubTransaction($clusterName, $orchestratorTxnId, $mySubTxnId, $orchestratorTxnId, $state, $description, $progress, $subTxnType );
  65. if ($subTransactionReturnValue["result"] != 0 ) {
  66. $logger->log_error("Got error while creating subTxn: ".$subTransactionReturnValue["error"]);
  67. print json_encode($subTransactionReturnValue);
  68. return;
  69. }
  70. }
  71. $clusterName = $argv[1];
  72. $deployUser = $argv[2];
  73. $rootTxnId = $argv[3];
  74. $readFromFile = $argv[4];
  75. $stagesFile = $argv[5];
  76. include_once $stagesFile;
  77. $logger->log_debug("Sequential runner params: $clusterName, $deployUser, $rootTxnId, $readFromFile, $stagesFile");
  78. // Create a sub-txn for the orchestrator
  79. $status = "";
  80. $createTxResult = HMCTxnUtils::createNewTransaction($dbHandle, $clusterName, $status);
  81. if ($createTxResult == FALSE) {
  82. $logger->log_error("Failed to create new transaction " . " in background: $createTxResult\n");
  83. return;
  84. }
  85. $orchestratorTxnId = $createTxResult;
  86. $logger->log_debug("Txn Id: $orchestratorTxnId\n");
  87. $state = ""; $description = "sequentialScriptExecutor"; $progress = ""; $subTxnType = "";
  88. $subTransactionReturnValue = $dbHandle->insertOrUpdateSubTransaction($clusterName, $rootTxnId, $orchestratorTxnId, $rootTxnId, $state, $description, $progress, $subTxnType );
  89. if ($subTransactionReturnValue["result"] != 0 ) {
  90. $logger->log_error("Got error while creating subTxn for sequentialScriptExecutor: ".$subTransactionReturnValue["error"]);
  91. print json_encode($subTransactionReturnValue);
  92. return;
  93. }
  94. $logger->log_debug("sequentialScriptExecutor txnId: $orchestratorTxnId\n");
  95. $startTime = time(0);
  96. $cmd = "";
  97. $currentStage = "";
  98. $statusInfo = "";
  99. $count = 0;
  100. $thisHostName = trim(strtolower(exec('hostname -f')));
  101. // Add the host which runs the server to the list
  102. function addThisHostToList($hosts, $logger, $thisHostName, $readFromFile) {
  103. $result = array();
  104. foreach($hosts as $host) {
  105. array_push($result, $host);
  106. if ($thisHostName == $host) {
  107. $logger->log_debug("Management host $thisHostName exists".
  108. " in the hosts file");
  109. return $hosts;
  110. }
  111. }
  112. $outFd = fopen($readFromFile, "a");
  113. if ($outFd == FALSE) {
  114. $logger->log_error("Failed to add the hmc host to the nodes file");
  115. return $result;
  116. }
  117. fwrite($outFd, "\n".$thisHostName);
  118. fclose($outFd);
  119. array_push($result, $thisHostName);
  120. return $result;
  121. }
  122. $hosts = readHostsFile($readFromFile);
  123. $hosts = convertToLowerCase($hosts);
  124. $logger->log_debug("The hosts after converting to lower case ".print_r($hosts, true));
  125. // Only add this host to list if the db does not have that host already.
  126. $checkThisHostInDB = $dbHandle->getHostInfo($clusterName, $thisHostName);
  127. $logger->log_debug("Host Info in DB ".print_r($checkThisHostInDB, true));
  128. if ($checkThisHostInDB["result"] != 0) {
  129. $logger->log_info($thisHostName . "not found in DB so adding it to the list of hosts");
  130. $hosts = addThisHostToList($hosts, $logger, $thisHostName, $readFromFile);
  131. }
  132. $hosts = convertToLowerCase($hosts);
  133. $logger->log_debug("The hosts that are being sshed to are ".print_r($hosts, true));
  134. $allHosts = $hosts; // Keep a copy in case
  135. foreach ($stagesInfo as $stage => $stageInfo) {
  136. // create a new subtransaction for each stage
  137. $mySubTxnId = 100 + $count;
  138. $state = ""; $description = $stagesInfo[$stage]["description"]; $progress = " ( starting )"; $subTxnType = "";
  139. $subTransactionReturnValue = $dbHandle->insertOrUpdateSubTransaction($clusterName, $orchestratorTxnId, $mySubTxnId, $orchestratorTxnId, $state, $description, $progress, $subTxnType );
  140. if ($subTransactionReturnValue["result"] != 0 ) {
  141. $logger->log_error("Got error while creating subTxn: ".$subTransactionReturnValue["error"]);
  142. print json_encode($subTransactionReturnValue);
  143. return;
  144. }
  145. $currentStage = $stage;
  146. // SubTxn is created. Set start op_status
  147. $updateSubTransactionStatusResult = $dbHandle->updateSubTransactionOpStatus($clusterName, $orchestratorTxnId, $mySubTxnId, $opStatus);
  148. if ($updateSubTransactionStatusResult["result"] != 0 ) {
  149. $logger->log_error("Got error while updating subTxn: ".$updateSubTransactionStatusResult["error"]);
  150. print json_encode($updateSubTransactionStatusResult);
  151. return;
  152. }
  153. // If the host list is empty, say because of failures in previous stage, no point carrying it on..
  154. $hostCount = count($hosts);
  155. if ($hostCount == 0) {
  156. $logger->log_info("Skipping stage " . $stage . " as no valid hosts available");
  157. continue; // so that all stages can get marked as failures
  158. }
  159. $cmd = $GLOBALS["PHP_EXEC_PATH"]." ".$stagesInfo[$stage]["scriptName"];
  160. $args = "$clusterName $deployUser $rootTxnId $mySubTxnId $orchestratorTxnId " . $readFromFile;
  161. $count++;
  162. $execBackgroundResult = HMCTxnUtils::execBackgroundProcess($dbHandle, $clusterName, $rootTxnId, $cmd, $args, "" );
  163. if ($execBackgroundResult == FALSE) {
  164. $logger->log_error("Failed to execute $currentStage".
  165. " in background: $execBackgroundResult\n");
  166. return;
  167. }
  168. $allSubTransactionsInfoResult = $dbHandle->getAllSubTransactionsInfo($clusterName, $orchestratorTxnId);
  169. if ($allSubTransactionsInfoResult["result"] != 0 ) {
  170. $logger->log_error("Got error while getting subTxnInfo: ".$allSubTransactionsInfoResult["error"]);
  171. print json_encode($allSubTransactionsInfoResult);
  172. return;
  173. }
  174. /*
  175. if (count($allSubTransactionsInfoResult["subTxns"]) != $count) {
  176. $logger->log_info("Still waiting ");
  177. }
  178. */
  179. //$mySubTxnId = '"'.$mySubTxnId.'"';
  180. // $logger->log_error(" sequentialScriptExecutors sub txns " . json_encode($allSubTransactionsInfoResult));
  181. $successStatus = "SUCCESS";
  182. $errorStatus = "FAILED";
  183. $totalFailedStatus = "TOTALFAILURE";
  184. $currentStatus = $allSubTransactionsInfoResult["subTxns"][$mySubTxnId]["opStatus"];
  185. while ( $currentStatus != $successStatus && $currentStatus != $errorStatus
  186. && $currentStatus != $totalFailedStatus) {
  187. sleep(1);
  188. $allSubTransactionsInfoResult = $dbHandle->getAllSubTransactionsInfo($clusterName, $orchestratorTxnId);
  189. if ($allSubTransactionsInfoResult["result"] != 0 ) {
  190. $logger->log_error("Got error while getting subTxnInfo: ".$allSubTransactionsInfoResult["error"]);
  191. print json_encode($allSubTransactionsInfoResult);
  192. return;
  193. }
  194. $currentStatus = $allSubTransactionsInfoResult["subTxns"][$mySubTxnId]["opStatus"];
  195. //$logger->log_debug(" sequentialScriptExecutors sub txns " . json_encode($allSubTransactionsInfoResult));
  196. if ($currentStatus != $successStatus && $currentStatus != $errorStatus
  197. && $currentStatus != $totalFailedStatus) {
  198. updateProgressForStage($clusterName, $rootTxnId,
  199. $orchestratorTxnId, $mySubTxnId, $stage, $hostCount);
  200. }
  201. //$logger->log_debug("Status we are seeing: " . $currentStatus . " txnId: " . $orchestratorTxnId . " subTxnId " . $mySubTxnId);
  202. }
  203. // Just in case, the command finished too fast and the while loop is skipped.
  204. updateProgressForStage($clusterName, $rootTxnId, $orchestratorTxnId, $mySubTxnId, $stage, $hostCount);
  205. $logger->log_debug("Came out of the launch for stage " . $currentStage . "\n");
  206. unset($subTxn);
  207. if ($currentStatus == $totalFailedStatus) {
  208. $logger->log_error("Encountered total failure in transaction $mySubTxnId" .
  209. " while running cmd: $cmd with args: $args");
  210. return;
  211. }
  212. ////////// Construct the host list needed for next stage ////////////
  213. $nextStageHosts = array();
  214. foreach ($hosts as $host) {
  215. ////// Get info about this node from db ////
  216. $hostInfo = $dbHandle->getHostInfo($clusterName,$host);
  217. if ($hostInfo["result"] != 0 ) {
  218. $logger->log_error("Got error while getting hostInfo for $host :" .$hostInfo["error"]);
  219. continue;
  220. }
  221. if ($hostInfo["discoveryStatus"] == "SUCCESS") {
  222. $nextStageHosts[] = $host;
  223. }
  224. }
  225. // Change the host list to weed-out bad nodes.
  226. $hosts = $nextStageHosts;
  227. ////////// End of constructructing the host list needed for next stage ////////////
  228. }
  229. ?>