addNodesProgress.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. function cleanUpTxnProgress () {
  22. globalYui.one('#installationWizardProgressBarDivId').setStyle('display', 'block');
  23. globalYui.one('#txnProgressStatusMessageDivId').setContent('');
  24. globalYui.one('#blackScreenDivId').setStyle('display', 'none');
  25. globalYui.one('#txnProgressStatusDivId').setStyle('display', 'none');
  26. globalYui.one('#addNodesCoreDivId').setStyle('display', 'none');
  27. globalYui.one('#txnProgressCoreDivId').setStyle('display', 'none');
  28. //globalYui.one('#txnProgressContentDivId').setContent
  29. // ( '<img id=txnProgressLoadingImgId class=loadingImg src=../images/loading.gif />' );
  30. }
  31. function generateSingleDiscoverProgressStateMarkup(discoverProgressStateTitle, progressState) {
  32. var stateClass;
  33. var barClass;
  34. switch (progressState) {
  35. case "SUCCESS":
  36. stateClass = 'txnProgressStateDone';
  37. barClass = 'progress progress-success';
  38. break;
  39. case "STARTING":
  40. case "STARTED":
  41. case "IN_PROGRESS":
  42. stateClass = 'txnProgressStateInProgress';
  43. //barClass = 'progress progress-striped active';
  44. barClass = 'progress';
  45. break;
  46. case "FAILED":
  47. case "TOTALFAILURE":
  48. stateClass = 'txnProgressStateError';
  49. barClass = 'progress progress-danger';
  50. break;
  51. default: // PENDING
  52. stateClass = 'txnProgressStatePending';
  53. barClass = 'progress';
  54. break;
  55. }
  56. var barMarkup = '<div class="' + barClass + '"><div class="bar"></div></div>';
  57. if (stateClass == 'txnProgressStateInProgress') {
  58. barMarkup = '<div id="activeProgressBarContainer">' + barMarkup + '</div>';
  59. }
  60. var markup = '<li><label class="' + stateClass + '">' + discoverProgressStateTitle + '</label>' + barMarkup + '</li>';
  61. //globalYui.log('progress state=' + progressState + ', markup=' + markup);
  62. return markup;
  63. }
  64. function renderProgress (discoverProgressInfo) {
  65. var txnProgressShown = false;
  66. var pollingStopped = false;
  67. var discoverProgressDataSource = new globalYui.DataSource.IO ({
  68. source: '../php/frontend/nodesActionProgress.php'
  69. });
  70. discoverProgressDataSource.plug(globalYui.Plugin.DataSourceJSONSchema, {
  71. schema: {
  72. metaFields: {
  73. progressStates: 'progressStates',
  74. currentProgressStateIndex: 'currentProgressStateIndex',
  75. encounteredError: 'encounteredError',
  76. stateInfo: 'stateInfo'
  77. }
  78. }
  79. });
  80. function clearActiveProgressBar() {
  81. var bar = globalYui.one('#activeProgressBar');
  82. if (bar != null) {
  83. bar.remove();
  84. }
  85. globalYui.on('windowresize', function(e) {
  86. setActiveProgressBarInPlace();
  87. });
  88. }
  89. function setActiveProgressBarInPlace() {
  90. // Puts an active progress bar where the placeholder with the DIV ID of "activeProgressBarSpot" is located.
  91. // Creates an instance of the active progress bar if one does not already exist
  92. // so that we can keep reusing it and moving it in place, rather than dynamically rendering it
  93. // on every successful callback to avoid flickering/disconnect due to animation.
  94. var bar = globalYui.one('#activeProgressBar');
  95. var barContainer = globalYui.one('#activeProgressBarContainer');
  96. if (barContainer != null) {
  97. if (bar == null) {
  98. globalYui.one("body").append('<div id="activeProgressBar" class="wrapped progress progress-striped active" style="position:absolute;top:-50px;left:0;z-index:99;"><div style="width:100%" class="bar"></div></div>');
  99. bar = globalYui.one('#activeProgressBar');
  100. }
  101. bar.setStyle('display', 'block');
  102. if (bar.getX() != barContainer.getX() || bar.getY() != barContainer.getY()) {
  103. bar.setXY(barContainer.getXY());
  104. }
  105. } else if (bar != null) {
  106. bar.setStyle('display', 'none');
  107. }
  108. }
  109. function runPollTask() {
  110. discoverProgressDataSource.sendRequest({
  111. request: '?clusterName=' + discoverProgressInfo.clusterName + '&txnId=' + discoverProgressInfo.txnId + '&action=addNodes',
  112. callback: {
  113. success: function (e) {
  114. if (pollingStopped) {
  115. return;
  116. }
  117. globalYui.one("#txnProgressHeader").setContent('Node Discovery and Preparation');
  118. var stateInfo = e.response.meta.stateInfo;
  119. var discoverProgressStates = e.response.meta.progressStates;
  120. var stateInfoLength = 0;
  121. var count = 0;
  122. var lastTxnId = 0;
  123. var discoverProgressMarkup = '<ul id="steps" class="wrapped">';
  124. var overallFail = false;
  125. var numSubTxns = 0;
  126. for (txnId in stateInfo.subTxns) {
  127. numSubTxns++;
  128. }
  129. if (numSubTxns == 0) {
  130. var errorInfoPanelBodyContent =
  131. '<img id="errorInfoPanelLoadingImgId" class="loadingImg" src="../images/loading.gif" />';
  132. globalYui.one('#txnProgressContentDivId').setContent( errorInfoPanelBodyContent );
  133. globalYui.one("#txnProgressCoreDivId").setStyle("display", "block");
  134. poll();
  135. return;
  136. }
  137. for (var txnId in stateInfo.subTxns) {
  138. var currentProgressState = stateInfo.subTxns[txnId].opStatus;
  139. // If all states are in pending or just the first one, let's mark the first one as in progress
  140. if (numSubTxns == 1 && currentProgressState != 'FAILED' && currentProgressState != 'TOTALFAILURE') {
  141. currentProgressState = "IN_PROGRESS";
  142. }
  143. discoverProgressMarkup +=
  144. generateSingleDiscoverProgressStateMarkup(
  145. stateInfo.subTxns[txnId].description + stateInfo.subTxns[txnId].progress,
  146. currentProgressState);
  147. stateInfoLength++;
  148. count++;
  149. lastTxnId = txnId;
  150. overallFail |= (currentProgressState == 'FAILED' || currentProgressState == 'TOTALFAILURE');
  151. }
  152. // Render the remaining stages as pending
  153. if (stateInfoLength < discoverProgressStates.length) {
  154. for (; count < discoverProgressStates.length; count++ ) {
  155. discoverProgressMarkup +=
  156. generateSingleDiscoverProgressStateMarkup(
  157. discoverProgressStates[count],
  158. 'PENDING');
  159. }
  160. }
  161. var noNeedForFurtherPolling = false;
  162. var totalFailure = false;
  163. var installationStatusDivContent = '';
  164. if (stateInfo.subTxns[lastTxnId].opStatus == "TOTALFAILURE") {
  165. noNeedForFurtherPolling = true;
  166. totalFailure = true;
  167. } else if (stateInfoLength == discoverProgressStates.length) {
  168. if ((stateInfo.subTxns[lastTxnId].opStatus == "SUCCESS")
  169. || (stateInfo.subTxns[lastTxnId].opStatus == "FAILED")) {
  170. noNeedForFurtherPolling = true;
  171. } else {
  172. noNeedForFurtherPolling = false;
  173. }
  174. }
  175. if( noNeedForFurtherPolling ) {
  176. /* We've made all the progress we could have, so stop polling. */
  177. pollingStopped = true;
  178. if (!overallFail) {
  179. statusContent =
  180. '<p>' +
  181. 'Finished node discovery and preparation. ' +
  182. '<a class="btn btn-large" href="javascript:void(null)" id="successInfoLinkId">' +
  183. 'Proceed to Select Services' +
  184. '</a>' +
  185. '</p>';
  186. globalYui.one('#txnProgressStatusDivId').removeClass('statusError');
  187. globalYui.one('#txnProgressStatusDivId').addClass('statusOk');
  188. globalYui.one('#txnProgressStatusMessageDivId').setContent(statusContent);
  189. globalYui.one("#successInfoLinkId").on( "click", function(e) {
  190. cleanUpTxnProgress();
  191. transitionToNextStage( "#txnProgressCoreDivId", discoverProgressInfo,
  192. "#selectServicesCoreDivId", discoverProgressInfo, renderSelectServicesBlock);
  193. });
  194. } else {
  195. statusContent =
  196. '<p>' +
  197. 'An error was encountered with some of the nodes.<br>' +
  198. 'Take a look at the <a href="javascript:void(null)" id=errorInfoLinkId>' +
  199. 'error logs</a> to see what might have happened.<br>';
  200. statusContent += '<a class="btn btn-large" style="margin:10px 0" href="javascript:void(null)"' +
  201. 'id="errorBackNavLinkId">Back to Add Nodes</a>';
  202. if (totalFailure == false) {
  203. statusContent += ' <a class="btn btn-large" href=' +
  204. '"javascript:void(null)" id="errorFwdNavLinkId" style="margin:10px 0 10px 20px">Ignore and Continue</a>';
  205. }
  206. statusContent += '</p>';
  207. globalYui.one('#txnProgressStatusDivId').removeClass('statusOk');
  208. globalYui.one('#txnProgressStatusDivId').addClass('statusError');
  209. globalYui.one('#txnProgressStatusMessageDivId').setContent(statusContent);
  210. // now can add the on-click feature for the links
  211. globalYui.one("#errorBackNavLinkId").on( "click", function(e) {
  212. cleanUpTxnProgress();
  213. errorInfoPanel.destroy();
  214. // give cleanup option
  215. // cleanupInstall();
  216. globalYui.one("#txnProgressStatusActionsDivId").setContent("");
  217. globalYui.one('#txnProgressCoreDivId').setStyle('display', 'none');
  218. globalYui.one("#addNodesCoreDivId").setStyle('display', 'block');
  219. });
  220. if (totalFailure == false) {
  221. globalYui.one("#errorFwdNavLinkId").on( "click", function(e) {
  222. cleanUpTxnProgress();
  223. errorInfoPanel.destroy();
  224. //REZYYY globalYui.one("#progressErrorInfoNavigateDivId").setContent("");
  225. globalYui.one("#txnProgressStatusActionsDivId").setContent("");
  226. transitionToNextStage( "#txnProgressCoreDivId", discoverProgressInfo,
  227. "#selectServicesCoreDivId", discoverProgressInfo, renderSelectServicesBlock);
  228. });
  229. }
  230. /* If we stopped polling due to error, we need to do more work. */
  231. /* Create the panel that'll display our error info. */
  232. var errorInfoPanel =
  233. createInformationalPanel( '#informationalPanelContainerDivId',
  234. 'Node Discovery and Preparation Logs' );
  235. globalYui.one("#errorInfoLinkId").on( "click", function(err) {
  236. var bodyContent = "";
  237. for (subTxn in e.response.meta.stateInfo.subTxns) {
  238. var subTxnInfo = e.response.meta.stateInfo.subTxns[subTxn];
  239. var additionalInfoTable = '<table>' +
  240. '<thead><tr><th>Host</th><th>Info</th></tr></thead>';
  241. for (hostName in subTxnInfo.state) {
  242. additionalInfoTable += '<tr><td>' + hostName + '</td><td><pre>' +subTxnInfo.state[hostName] + '</pre></td></tr>'
  243. }
  244. additionalInfoTable += '</table>';
  245. bodyContent += '<div class="logEntry">' +
  246. '<div class="logEntryHeader">' + subTxnInfo.description + '</div>' +
  247. '<div class="logEntryBody">' +
  248. '<ul>' +
  249. '<li>Entry Id : ' + subTxnInfo.subTxnId + '</li>' +
  250. '<li>Final result : ' + subTxnInfo.opStatus + '</li>' +
  251. '<li>Progress at the end : ' + subTxnInfo.progress + '</li>' +
  252. '<li>Additional information : ' + additionalInfoTable + '</li>' +
  253. '</ul>' +
  254. '</div>' +
  255. '</div>';
  256. }
  257. errorInfoPanel.set('bodyContent' , bodyContent);
  258. //errorInfoPanel.set( 'bodyContent', '<pre>' +
  259. // globalYui.JSON.stringify( e.response.meta.stateInfo, null, 4) + '</pre>' );
  260. errorInfoPanel.show();
  261. //REZYYY globalYui.one("#progressErrorInfoNavigateDivId").setStyle( 'display', 'block' );
  262. });
  263. } // end if error
  264. globalYui.one('#txnProgressStatusDivId').setStyle('display', 'block');
  265. } // end no need for further polling
  266. discoverProgressMarkup += '</ul>';
  267. globalYui.log('About to generate markup: ' + discoverProgressMarkup);
  268. globalYui.one('#txnProgressContentDivId').setContent(discoverProgressMarkup);
  269. if (!txnProgressShown) {
  270. globalYui.one('#txnProgressCoreDivId').setStyle('display','block');
  271. txnProgressShown = true;
  272. }
  273. setActiveProgressBarInPlace();
  274. if (!pollingStopped) {
  275. poll();
  276. }
  277. },
  278. failure: function (e) {
  279. alert('Failed to fetch more progress!');
  280. /* No point making any more attempts. */
  281. pollingStopped = true;
  282. }
  283. }
  284. });
  285. }
  286. function poll() {
  287. window.setTimeout(runPollTask, 3000);
  288. }
  289. clearActiveProgressBar();
  290. runPollTask();
  291. }