step3_controller.js 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var lazyloading = require('utils/lazy_loading');
  20. var numberUtils = require('utils/number_utils');
  21. App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, {
  22. name: 'wizardStep3Controller',
  23. hosts: [],
  24. content: [],
  25. bootHosts: [],
  26. registeredHosts: [],
  27. /**
  28. * @typedef {{
  29. * name: string,
  30. * hosts: string[],
  31. * hostsLong: string[],
  32. * hostsNames: string[],
  33. * onSingleHost: boolean
  34. * }} checkWarning
  35. */
  36. /**
  37. * @type {checkWarning[]}
  38. */
  39. hostCheckWarnings: [],
  40. /**
  41. * @type {checkWarning[]}
  42. */
  43. repoCategoryWarnings: [],
  44. /**
  45. * @type {checkWarning[]}
  46. */
  47. diskCategoryWarnings: [],
  48. /**
  49. * @type {checkWarning[]}
  50. */
  51. thpCategoryWarnings: [],
  52. /**
  53. * @type {checkWarning[]}
  54. */
  55. jdkCategoryWarnings: null,
  56. jdkRequestIndex: null,
  57. registrationStartedAt: null,
  58. requestId: 0,
  59. /**
  60. * Timeout for registration
  61. * Based on <code>installOptions.manualInstall</code>
  62. * @type {number}
  63. */
  64. registrationTimeoutSecs: function () {
  65. return this.get('content.installOptions.manualInstall') ? 15 : 120;
  66. }.property('content.installOptions.manualInstall'),
  67. /**
  68. * Bootstrap calls are stopped
  69. * @type {bool}
  70. */
  71. stopBootstrap: false,
  72. /**
  73. * is Submit button disabled
  74. * @type {bool}
  75. */
  76. isSubmitDisabled: true,
  77. /**
  78. * True if bootstrap POST request failed
  79. * @type {bool}
  80. */
  81. isBootstrapFailed: false,
  82. /**
  83. * is Retry button disabled
  84. * @type {bool}
  85. */
  86. isRetryDisabled: function() {
  87. return (this.get('isBackDisabled')) ? this.get('isBackDisabled') : !this.get('bootHosts').filterProperty('bootStatus', 'FAILED').length;
  88. }.property('bootHosts.@each.bootStatus', 'isBackDisabled'),
  89. /**
  90. * Is Back button disabled
  91. * @return {bool}
  92. */
  93. isBackDisabled: function () {
  94. return (this.get('isRegistrationInProgress') || !this.get('isWarningsLoaded')) && !this.get('isBootstrapFailed');
  95. }.property('isRegistrationInProgress', 'isWarningsLoaded', 'isBootstrapFailed'),
  96. /**
  97. * Controller is using in Add Host Wizard
  98. * @return {bool}
  99. */
  100. isAddHostWizard: function () {
  101. return this.get('content.controllerName') === 'addHostController';
  102. }.property('content.controllerName'),
  103. /**
  104. * @type {bool}
  105. */
  106. isLoaded: false,
  107. /**
  108. * Polls count
  109. * @type {number}
  110. */
  111. numPolls: 0,
  112. /**
  113. * Is hosts registration in progress
  114. * @type {bool}
  115. */
  116. isRegistrationInProgress: true,
  117. /**
  118. * Are some registered hosts which are not added by user
  119. * @type {bool}
  120. */
  121. hasMoreRegisteredHosts: false,
  122. /**
  123. * Contain data about installed packages on hosts
  124. * @type {Array}
  125. */
  126. hostsPackagesData: [],
  127. /**
  128. * List of installed hostnames
  129. * @type {string[]}
  130. */
  131. hostsInCluster: function () {
  132. var installedHostsName = [];
  133. var hosts = this.get('content.hosts');
  134. for (var hostName in hosts) {
  135. if (hosts[hostName].isInstalled) {
  136. installedHostsName.push(hostName);
  137. }
  138. }
  139. return installedHostsName;
  140. }.property('content.hosts'),
  141. /**
  142. * All hosts warnings
  143. * @type {object[]}
  144. */
  145. warnings: [],
  146. /**
  147. * Warnings grouped by host
  148. * @type {Ember.Enumerable}
  149. */
  150. warningsByHost: [],
  151. /**
  152. * Timeout for "warning"-requests
  153. * @type {number}
  154. */
  155. warningsTimeInterval: 60000,
  156. /**
  157. * Are hosts warnings loaded
  158. * @type {bool}
  159. */
  160. isWarningsLoaded: function () {
  161. return this.get('isJDKWarningsLoaded') && this.get('isHostsWarningsLoaded');
  162. }.property('isJDKWarningsLoaded', 'isHostsWarningsLoaded'),
  163. /**
  164. * Check are hosts have any warnings
  165. * @type {bool}
  166. */
  167. isHostHaveWarnings: function () {
  168. return this.get('warnings.length') > 0;
  169. }.property('warnings'),
  170. /**
  171. * Should warnings-box be visible
  172. * @type {bool}
  173. */
  174. isWarningsBoxVisible: function () {
  175. return (App.get('testMode')) ? true : !this.get('isRegistrationInProgress');
  176. }.property('isRegistrationInProgress'),
  177. /**
  178. * Progress value for "update hosts status" process
  179. * @type {number}
  180. */
  181. checksUpdateProgress: 0,
  182. /**
  183. *
  184. * @type {object}
  185. */
  186. checksUpdateStatus: null,
  187. /**
  188. *
  189. * @method navigateStep
  190. */
  191. navigateStep: function () {
  192. if (this.get('isLoaded')) {
  193. if (!this.get('content.installOptions.manualInstall')) {
  194. if (!this.get('wizardController').getDBProperty('bootStatus')) {
  195. this.setupBootStrap();
  196. }
  197. } else {
  198. this.set('bootHosts', this.get('hosts'));
  199. if (App.get('testMode')) {
  200. this.startHostcheck();
  201. this.get('bootHosts').setEach('cpu', '2');
  202. this.get('bootHosts').setEach('memory', '2000000');
  203. this.set('isSubmitDisabled', false);
  204. } else {
  205. this.set('registrationStartedAt', null);
  206. this.startRegistration();
  207. }
  208. }
  209. }
  210. }.observes('isLoaded'),
  211. /**
  212. * Clear controller data
  213. * @method clearStep
  214. */
  215. clearStep: function () {
  216. this.set('stopBootstrap', false);
  217. this.set('hosts', []);
  218. this.get('bootHosts').clear();
  219. this.get('wizardController').setDBProperty('bootStatus', false);
  220. this.set('isHostsWarningsLoaded', false);
  221. this.set('isJDKWarningsLoaded', false);
  222. this.set('registrationStartedAt', null);
  223. this.set('isLoaded', false);
  224. this.set('isSubmitDisabled', true);
  225. this.set('stopChecking', false);
  226. },
  227. /**
  228. * setup bootstrap data and completion callback for bootstrap call
  229. * @method setupBootStrap
  230. */
  231. setupBootStrap: function () {
  232. var self = this;
  233. var bootStrapData = JSON.stringify({
  234. 'verbose': true,
  235. 'sshKey': this.get('content.installOptions.sshKey'),
  236. 'hosts': this.getBootstrapHosts(),
  237. 'user': this.get('content.installOptions.sshUser'),
  238. 'userRunAs': App.get('supports.customizeAgentUserAccount') ? this.get('content.installOptions.agentUser') : 'root'
  239. });
  240. App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
  241. if (requestId == '0') {
  242. self.startBootstrap();
  243. } else if (requestId) {
  244. self.set('content.installOptions.bootRequestId', requestId);
  245. App.router.get(self.get('content.controllerName')).save('installOptions');
  246. self.startBootstrap();
  247. }
  248. });
  249. },
  250. getBootstrapHosts: function () {
  251. var hosts = this.get('content.hosts');
  252. var bootstrapHosts = [];
  253. for (var host in hosts) {
  254. if (hosts.hasOwnProperty(host)) {
  255. if (!hosts[host].isInstalled) {
  256. bootstrapHosts.push(host);
  257. }
  258. }
  259. }
  260. return bootstrapHosts;
  261. },
  262. /**
  263. * Make basic init steps
  264. * @method loadStep
  265. */
  266. loadStep: function () {
  267. console.log("TRACE: Loading step3: Confirm Hosts");
  268. var wizardController = this.get('wizardController');
  269. var previousStep = wizardController && wizardController.get('previousStep');
  270. var currentStep = wizardController && wizardController.get('currentStep');
  271. var isHostsLoaded = this.get('hosts').length !== 0;
  272. var isPrevAndCurrStepsSetted = previousStep && currentStep;
  273. var isPrevStepSmallerThenCurrent = previousStep < currentStep;
  274. if (!isHostsLoaded || isPrevStepSmallerThenCurrent ||
  275. !wizardController || !isPrevAndCurrStepsSetted) {
  276. this.disablePreviousSteps();
  277. this.clearStep();
  278. App.router.get('clusterController').loadAmbariProperties();
  279. this.loadHosts();
  280. }
  281. },
  282. /**
  283. * Loads the hostinfo from localStorage on the insertion of view. It's being called from view
  284. * @method loadHosts
  285. */
  286. loadHosts: function () {
  287. var hostsInfo = this.get('content.hosts');
  288. var hosts = [];
  289. var bootStatus = (this.get('content.installOptions.manualInstall')) ? 'DONE' : 'PENDING';
  290. if (App.get('testMode')) {
  291. bootStatus = 'REGISTERED';
  292. }
  293. for (var index in hostsInfo) {
  294. if (hostsInfo.hasOwnProperty(index) && !hostsInfo[index].isInstalled) {
  295. hosts.pushObject(App.HostInfo.create({
  296. name: hostsInfo[index].name,
  297. bootStatus: bootStatus,
  298. isChecked: false
  299. }));
  300. }
  301. }
  302. this.set('hosts', hosts);
  303. this.set('isLoaded', true);
  304. },
  305. /**
  306. * Parses and updates the content based on bootstrap API response.
  307. * @return {bool} true if polling should continue (some hosts are in "RUNNING" state); false otherwise
  308. * @method parseHostInfo
  309. */
  310. parseHostInfo: function (hostsStatusFromServer) {
  311. hostsStatusFromServer.forEach(function (_hostStatus) {
  312. var host = this.get('bootHosts').findProperty('name', _hostStatus.hostName);
  313. // check if hostname extracted from REST API data matches any hostname in content
  314. // also, make sure that bootStatus modified by isHostsRegistered call does not get overwritten
  315. // since these calls are being made in parallel
  316. if (host && !['REGISTERED', 'REGISTERING'].contains(host.get('bootStatus'))) {
  317. host.set('bootStatus', _hostStatus.status);
  318. host.set('bootLog', _hostStatus.log);
  319. }
  320. }, this);
  321. // if the data rendered by REST API has hosts in "RUNNING" state, polling will continue
  322. return this.get('bootHosts').length != 0 && this.get('bootHosts').someProperty('bootStatus', 'RUNNING');
  323. },
  324. /**
  325. * Remove list of hosts
  326. * @param {Ember.Enumerable} hosts
  327. * @return {App.ModalPopup}
  328. * @method removeHosts
  329. */
  330. removeHosts: function (hosts) {
  331. var self = this;
  332. return App.showConfirmationPopup(function () {
  333. App.router.send('removeHosts', hosts);
  334. self.hosts.removeObjects(hosts);
  335. self.stopRegistration();
  336. if (!self.hosts.length) {
  337. self.set('isSubmitDisabled', true);
  338. }
  339. }, Em.I18n.t('installer.step3.hosts.remove.popup.body'));
  340. },
  341. /**
  342. * Removes a single element on the trash icon click. Called from View
  343. * @param {object} hostInfo
  344. * @method removeHost
  345. */
  346. removeHost: function (hostInfo) {
  347. if (!this.get('isBackDisabled'))
  348. this.removeHosts([hostInfo]);
  349. },
  350. /**
  351. * Remove selected hosts (click-handler)
  352. * @return App.ModalPopup
  353. * @method removeSelectedHosts
  354. */
  355. removeSelectedHosts: function () {
  356. var selectedHosts = this.get('hosts').filterProperty('isChecked', true);
  357. selectedHosts.forEach(function (_hostInfo) {
  358. console.log('Removing: ' + _hostInfo.name);
  359. });
  360. return this.removeHosts(selectedHosts);
  361. },
  362. /**
  363. * Show popup with the list of hosts which are selected
  364. * @return App.ModalPopup
  365. * @method selectedHostsPopup
  366. */
  367. selectedHostsPopup: function () {
  368. var selectedHosts = this.get('hosts').filterProperty('isChecked').mapProperty('name');
  369. return App.ModalPopup.show({
  370. header: Em.I18n.t('installer.step3.selectedHosts.popup.header'),
  371. secondary: null,
  372. bodyClass: Em.View.extend({
  373. templateName: require('templates/common/items_list_popup'),
  374. items: selectedHosts,
  375. insertedItems: [],
  376. didInsertElement: function () {
  377. lazyloading.run({
  378. destination: this.get('insertedItems'),
  379. source: this.get('items'),
  380. context: this,
  381. initSize: 100,
  382. chunkSize: 500,
  383. delay: 100
  384. });
  385. }
  386. })
  387. });
  388. },
  389. /**
  390. * Retry one host {click-handler}
  391. * @param {object} hostInfo
  392. * @method retryHost
  393. */
  394. retryHost: function (hostInfo) {
  395. this.retryHosts([hostInfo]);
  396. },
  397. /**
  398. * Retry list of hosts
  399. * @param {object[]} hosts
  400. * @method retryHosts
  401. */
  402. retryHosts: function (hosts) {
  403. var self = this;
  404. var bootStrapData = JSON.stringify({
  405. 'verbose': true,
  406. 'sshKey': this.get('content.installOptions.sshKey'),
  407. 'hosts': hosts.mapProperty('name'),
  408. 'user': this.get('content.installOptions.sshUser'),
  409. 'userRunAs': App.get('supports.customizeAgentUserAccount') ? this.get('content.installOptions.agentUser') : 'root'
  410. });
  411. this.set('numPolls', 0);
  412. this.set('registrationStartedAt', null);
  413. this.set('isHostsWarningsLoaded', false);
  414. this.set('stopChecking', false);
  415. this.set('isSubmitDisabled', true);
  416. if (this.get('content.installOptions.manualInstall')) {
  417. this.startRegistration();
  418. } else {
  419. App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
  420. self.set('content.installOptions.bootRequestId', requestId);
  421. self.doBootstrap();
  422. });
  423. }
  424. },
  425. /**
  426. * Retry selected hosts (click-handler)
  427. * @method retrySelectedHosts
  428. */
  429. retrySelectedHosts: function () {
  430. if (!this.get('isRetryDisabled')) {
  431. var selectedHosts = this.get('bootHosts').filterProperty('bootStatus', 'FAILED');
  432. selectedHosts.forEach(function (_host) {
  433. _host.set('bootStatus', 'DONE');
  434. _host.set('bootLog', 'Retrying ...');
  435. }, this);
  436. this.retryHosts(selectedHosts);
  437. }
  438. },
  439. /**
  440. * Init bootstrap settings and start it
  441. * @method startBootstrap
  442. */
  443. startBootstrap: function () {
  444. //this.set('isSubmitDisabled', true); //TODO: uncomment after actual hookup
  445. this.set('numPolls', 0);
  446. this.set('registrationStartedAt', null);
  447. this.set('bootHosts', this.get('hosts'));
  448. this.doBootstrap();
  449. },
  450. /**
  451. * Update <code>isRegistrationInProgress</code> once
  452. * @method setRegistrationInProgressOnce
  453. */
  454. setRegistrationInProgressOnce: function () {
  455. Em.run.once(this, 'setRegistrationInProgress');
  456. }.observes('bootHosts.@each.bootStatus'),
  457. /**
  458. * Set <code>isRegistrationInProgress</code> value based on each host boot status
  459. * @method setRegistrationInProgress
  460. */
  461. setRegistrationInProgress: function () {
  462. var bootHosts = this.get('bootHosts');
  463. //if hosts aren't loaded yet then registration should be in progress
  464. var result = (bootHosts.length === 0 && !this.get('isLoaded'));
  465. for (var i = 0, l = bootHosts.length; i < l; i++) {
  466. if (bootHosts[i].get('bootStatus') !== 'REGISTERED' && bootHosts[i].get('bootStatus') !== 'FAILED') {
  467. result = true;
  468. break;
  469. }
  470. }
  471. this.set('isRegistrationInProgress', result);
  472. },
  473. /**
  474. * Disable wizard's previous steps (while registering)
  475. * @method disablePreviousSteps
  476. */
  477. disablePreviousSteps: function () {
  478. App.router.get('installerController.isStepDisabled').filter(function (step) {
  479. return step.step >= 0 && step.step <= 2;
  480. }).setEach('value', this.get('isBackDisabled'));
  481. App.router.get('addHostController.isStepDisabled').filter(function (step) {
  482. return step.step >= 0 && step.step <= 1;
  483. }).setEach('value', this.get('isBackDisabled'));
  484. }.observes('isBackDisabled'),
  485. /**
  486. * Do bootstrap calls
  487. * @method doBootstrap
  488. * @return {$.ajax|null}
  489. */
  490. doBootstrap: function () {
  491. if (this.get('stopBootstrap')) {
  492. return null;
  493. }
  494. this.incrementProperty('numPolls');
  495. return App.ajax.send({
  496. name: 'wizard.step3.bootstrap',
  497. sender: this,
  498. data: {
  499. bootRequestId: this.get('content.installOptions.bootRequestId'),
  500. numPolls: this.get('numPolls'),
  501. errorLogMessage: 'Bootstrap failed',
  502. callback: this.doBootstrap,
  503. shouldUseDefaultHandler: true
  504. },
  505. success: 'doBootstrapSuccessCallback',
  506. error: 'reloadErrorCallback'
  507. });
  508. },
  509. /**
  510. * Success-callback for each boostrap request
  511. * @param {object} data
  512. * @method doBootstrapSuccessCallback
  513. */
  514. doBootstrapSuccessCallback: function (data) {
  515. var self = this;
  516. var pollingInterval = 3000;
  517. this.reloadSuccessCallback();
  518. if (Em.isNone(data.hostsStatus)) {
  519. console.log('Invalid response, setting timeout');
  520. window.setTimeout(function () {
  521. self.doBootstrap()
  522. }, pollingInterval);
  523. } else {
  524. // in case of bootstrapping just one host, the server returns an object rather than an array, so
  525. // force into an array
  526. if (!(data.hostsStatus instanceof Array)) {
  527. data.hostsStatus = [ data.hostsStatus ];
  528. }
  529. console.log("TRACE: In success function for the GET bootstrap call");
  530. var keepPolling = this.parseHostInfo(data.hostsStatus);
  531. // Single host : if the only hostname is invalid (data.status == 'ERROR')
  532. // Multiple hosts : if one or more hostnames are invalid
  533. // following check will mark the bootStatus as 'FAILED' for the invalid hostname
  534. var installedHosts = App.Host.find().mapProperty('hostName');
  535. var isErrorStatus = data.status == 'ERROR';
  536. this.set('isBootstrapFailed', isErrorStatus);
  537. if (isErrorStatus || data.hostsStatus.mapProperty('hostName').removeObjects(installedHosts).length != this.get('bootHosts').length) {
  538. var hosts = this.get('bootHosts');
  539. for (var i = 0; i < hosts.length; i++) {
  540. var isValidHost = data.hostsStatus.someProperty('hostName', hosts[i].get('name'));
  541. if (hosts[i].get('bootStatus') !== 'REGISTERED') {
  542. if (!isValidHost) {
  543. hosts[i].set('bootStatus', 'FAILED');
  544. hosts[i].set('bootLog', Em.I18n.t('installer.step3.hosts.bootLog.failed'));
  545. }
  546. }
  547. }
  548. }
  549. if (isErrorStatus || data.hostsStatus.someProperty('status', 'DONE') || data.hostsStatus.someProperty('status', 'FAILED')) {
  550. // kicking off registration polls after at least one host has succeeded
  551. this.startRegistration();
  552. }
  553. if (keepPolling) {
  554. window.setTimeout(function () {
  555. self.doBootstrap()
  556. }, pollingInterval);
  557. }
  558. }
  559. },
  560. /**
  561. * Start hosts registration
  562. * @method startRegistration
  563. */
  564. startRegistration: function () {
  565. if (Em.isNone(this.get('registrationStartedAt'))) {
  566. this.set('registrationStartedAt', App.dateTime());
  567. console.log('registration started at ' + this.get('registrationStartedAt'));
  568. this.isHostsRegistered();
  569. }
  570. },
  571. /**
  572. * Do requests to check if hosts are already registered
  573. * @return {$.ajax|null}
  574. * @method isHostsRegistered
  575. */
  576. isHostsRegistered: function () {
  577. if (this.get('stopBootstrap')) {
  578. return null;
  579. }
  580. return App.ajax.send({
  581. name: 'wizard.step3.is_hosts_registered',
  582. sender: this,
  583. success: 'isHostsRegisteredSuccessCallback',
  584. error: 'reloadErrorCallback',
  585. data: {
  586. errorLogMessage: 'Error: Getting registered host information from the server',
  587. callback: this.isHostsRegistered,
  588. shouldUseDefaultHandler: true
  589. }
  590. });
  591. },
  592. /**
  593. * Success-callback for registered hosts request
  594. * @param {object} data
  595. * @method isHostsRegisteredSuccessCallback
  596. */
  597. isHostsRegisteredSuccessCallback: function (data) {
  598. console.log('registration attempt...');
  599. var hosts = this.get('bootHosts');
  600. var jsonData = data;
  601. this.reloadSuccessCallback();
  602. if (!jsonData) {
  603. console.warn("Error: jsonData is null");
  604. return;
  605. }
  606. // keep polling until all hosts have registered/failed, or registrationTimeout seconds after the last host finished bootstrapping
  607. var stopPolling = true;
  608. hosts.forEach(function (_host, index) {
  609. // Change name of first host for test mode.
  610. if (App.get('testMode')) {
  611. if (index == 0) {
  612. _host.set('name', 'localhost.localdomain');
  613. }
  614. }
  615. // actions to take depending on the host's current bootStatus
  616. // RUNNING - bootstrap is running; leave it alone
  617. // DONE - bootstrap is done; transition to REGISTERING
  618. // REGISTERING - bootstrap is done but has not registered; transition to REGISTERED if host found in polling API result
  619. // REGISTERED - bootstrap and registration is done; leave it alone
  620. // FAILED - either bootstrap or registration failed; leave it alone
  621. switch (_host.get('bootStatus')) {
  622. case 'DONE':
  623. _host.set('bootStatus', 'REGISTERING');
  624. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
  625. // update registration timestamp so that the timeout is computed from the last host that finished bootstrapping
  626. this.set('registrationStartedAt', App.dateTime());
  627. stopPolling = false;
  628. break;
  629. case 'REGISTERING':
  630. if (jsonData.items.someProperty('Hosts.host_name', _host.name) && !jsonData.items.filterProperty('Hosts.host_name', _host.name).someProperty('Hosts.host_status', 'UNKNOWN')) {
  631. _host.set('bootStatus', 'REGISTERED');
  632. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
  633. } else {
  634. stopPolling = false;
  635. }
  636. break;
  637. case 'RUNNING':
  638. stopPolling = false;
  639. break;
  640. case 'REGISTERED':
  641. case 'FAILED':
  642. default:
  643. break;
  644. }
  645. }, this);
  646. if (stopPolling) {
  647. this.startHostcheck();
  648. }
  649. else {
  650. if (hosts.someProperty('bootStatus', 'RUNNING') || App.dateTime() - this.get('registrationStartedAt') < this.get('registrationTimeoutSecs') * 1000) {
  651. // we want to keep polling for registration status if any of the hosts are still bootstrapping (so we check for RUNNING).
  652. var self = this;
  653. window.setTimeout(function () {
  654. self.isHostsRegistered();
  655. }, 3000);
  656. }
  657. else {
  658. // registration timed out. mark all REGISTERING hosts to FAILED
  659. console.log('registration timed out');
  660. hosts.filterProperty('bootStatus', 'REGISTERING').forEach(function (_host) {
  661. _host.set('bootStatus', 'FAILED');
  662. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.failed'));
  663. });
  664. this.startHostcheck();
  665. }
  666. }
  667. },
  668. /**
  669. * Do request for all registered hosts
  670. * @return {$.ajax}
  671. * @method getAllRegisteredHosts
  672. */
  673. getAllRegisteredHosts: function () {
  674. return App.ajax.send({
  675. name: 'wizard.step3.is_hosts_registered',
  676. sender: this,
  677. success: 'getAllRegisteredHostsCallback'
  678. });
  679. }.observes('bootHosts'),
  680. /**
  681. * Success-callback for all registered hosts request
  682. * @param {object} hosts
  683. * @method getAllRegisteredHostsCallback
  684. */
  685. getAllRegisteredHostsCallback: function (hosts) {
  686. var registeredHosts = [];
  687. var hostsInCluster = this.get('hostsInCluster');
  688. var addedHosts = this.get('bootHosts').getEach('name');
  689. hosts.items.forEach(function (host) {
  690. if (!hostsInCluster.contains(host.Hosts.host_name) && !addedHosts.contains(host.Hosts.host_name)) {
  691. registeredHosts.push(host.Hosts.host_name);
  692. }
  693. });
  694. if (registeredHosts.length) {
  695. this.set('hasMoreRegisteredHosts', true);
  696. this.set('registeredHosts', registeredHosts);
  697. } else {
  698. this.set('hasMoreRegisteredHosts', false);
  699. this.set('registeredHosts', '');
  700. }
  701. },
  702. /**
  703. * Show popup with regitration error-message
  704. * @param {string} header
  705. * @param {string} message
  706. * @return {App.ModalPopup}
  707. * @method registerErrPopup
  708. */
  709. registerErrPopup: function (header, message) {
  710. return App.ModalPopup.show({
  711. header: header,
  712. secondary: false,
  713. bodyClass: Em.View.extend({
  714. template: Em.Handlebars.compile('<p>{{view.message}}</p>'),
  715. message: message
  716. })
  717. });
  718. },
  719. /**
  720. * Get JDK name from server to determine if user had setup a customized JDK path when doing 'ambari-server setup'.
  721. * The Ambari properties are different from default ambari-server setup, property 'jdk.name' will be missing if a customized jdk path is applied.
  722. * @return {$.ajax}
  723. * @method getJDKName
  724. */
  725. getJDKName: function () {
  726. return App.ajax.send({
  727. name: 'ambari.service',
  728. sender: this,
  729. data: {
  730. fields : '?fields=RootServiceComponents/properties/jdk.name,RootServiceComponents/properties/java.home,RootServiceComponents/properties/jdk_location'
  731. },
  732. success: 'getJDKNameSuccessCallback'
  733. });
  734. },
  735. /**
  736. * Success callback for JDK name, property 'jdk.name' will be missing if a customized jdk path is applied
  737. * @param {object} data
  738. * @method getJDKNameSuccessCallback
  739. */
  740. getJDKNameSuccessCallback: function (data) {
  741. this.set('needJDKCheckOnHosts', !data.RootServiceComponents.properties["jdk.name"]);
  742. this.set('jdkLocation', Em.get(data, "RootServiceComponents.properties.jdk_location"));
  743. this.set('javaHome', data.RootServiceComponents.properties["java.home"]);
  744. },
  745. doCheckJDK: function () {
  746. var hostsNames = (!this.get('content.installOptions.manualInstall')) ? this.get('bootHosts').filterProperty('bootStatus', 'REGISTERED').getEach('name').join(",") : this.get('bootHosts').getEach('name').join(",");
  747. var javaHome = this.get('javaHome');
  748. var jdkLocation = this.get('jdkLocation');
  749. App.ajax.send({
  750. name: 'wizard.step3.jdk_check',
  751. sender: this,
  752. data: {
  753. host_names: hostsNames,
  754. java_home: javaHome,
  755. jdk_location: jdkLocation
  756. },
  757. success: 'doCheckJDKsuccessCallback',
  758. error: 'doCheckJDKerrorCallback'
  759. });
  760. },
  761. doCheckJDKsuccessCallback: function (data) {
  762. if(data){
  763. this.set('jdkRequestIndex', data.href.split('/')[data.href.split('/').length - 1]);
  764. }
  765. if (this.get('jdkCategoryWarnings') == null) {
  766. // get jdk check results for all hosts
  767. App.ajax.send({
  768. name: 'wizard.step3.jdk_check.get_results',
  769. sender: this,
  770. data: {
  771. requestIndex: this.get('jdkRequestIndex')
  772. },
  773. success: 'parseJDKCheckResults'
  774. })
  775. } else {
  776. this.set('isJDKWarningsLoaded', true);
  777. }
  778. },
  779. doCheckJDKerrorCallback: function () {
  780. console.log('INFO: Doing JDK check for host failed');
  781. this.set('isJDKWarningsLoaded', true);
  782. },
  783. parseJDKCheckResults: function (data) {
  784. var jdkWarnings = [], hostsJDKContext = [], hostsJDKNames = [];
  785. // check if the request ended
  786. if (data.Requests.end_time > 0 && data.tasks) {
  787. data.tasks.forEach( function(task) {
  788. // generate warning context
  789. if (Em.get(task, "Tasks.structured_out.java_home_check.exit_code") == 1){
  790. var jdkContext = Em.I18n.t('installer.step3.hostWarningsPopup.jdk.context').format(task.Tasks.host_name);
  791. hostsJDKContext.push(jdkContext);
  792. hostsJDKNames.push(task.Tasks.host_name);
  793. }
  794. });
  795. if (hostsJDKContext.length > 0) { // java jdk warning exist
  796. var invalidJavaHome = this.get('javaHome');
  797. jdkWarnings.push({
  798. name: Em.I18n.t('installer.step3.hostWarningsPopup.jdk.name').format(invalidJavaHome),
  799. hosts: hostsJDKContext,
  800. hostsLong: hostsJDKContext,
  801. hostsNames: hostsJDKNames,
  802. category: 'jdk',
  803. onSingleHost: false
  804. });
  805. }
  806. this.set('jdkCategoryWarnings', jdkWarnings);
  807. } else {
  808. // still doing JDK check, data not ready to be parsed
  809. this.set('jdkCategoryWarnings', null);
  810. }
  811. this.doCheckJDKsuccessCallback();
  812. },
  813. /**
  814. * Check JDK issues on registered hosts.
  815. */
  816. checkHostJDK: function () {
  817. this.set('isJDKWarningsLoaded', false);
  818. this.set('jdkCategoryWarnings', null);
  819. var self = this;
  820. this.getJDKName().done( function() {
  821. if (self.get('needJDKCheckOnHosts')) {
  822. // need to do JDK check on each host
  823. self.doCheckJDK();
  824. } else {
  825. // no customized JDK path, so no need to check jdk
  826. self.set('jdkCategoryWarnings', []);
  827. self.set('isJDKWarningsLoaded', true);
  828. }
  829. });
  830. },
  831. /**
  832. * Get disk info and cpu count of booted hosts from server
  833. * @return {$.ajax}
  834. * @method getHostInfo
  835. */
  836. getHostInfo: function () {
  837. this.set('isHostsWarningsLoaded', false);
  838. // begin JDK check for each host
  839. return App.ajax.send({
  840. name: 'wizard.step3.host_info',
  841. sender: this,
  842. success: 'getHostInfoSuccessCallback',
  843. error: 'getHostInfoErrorCallback'
  844. });
  845. },
  846. startHostcheck: function() {
  847. this.set('isWarningsLoaded', false);
  848. this.getHostNameResolution();
  849. this.checkHostJDK();
  850. },
  851. getHostNameResolution: function () {
  852. if (App.get('testMode')) {
  853. this.getHostCheckSuccess();
  854. } else {
  855. var data = this.getDataForCheckRequest("host_resolution_check", true);
  856. data ? this.requestToPerformHostCheck(data) : this.stopHostCheck();
  857. }
  858. },
  859. getGeneralHostCheck: function () {
  860. if (App.get('testMode')) {
  861. this.getHostInfo();
  862. } else {
  863. var data = this.getDataForCheckRequest("last_agent_env_check,installed_packages,existing_repos,transparentHugePage", false);
  864. data ? this.requestToPerformHostCheck(data) : this.stopHostCheck();
  865. }
  866. },
  867. /**
  868. * set all fields from which depends running host check to true value
  869. * which force finish checking;
  870. */
  871. stopHostCheck: function() {
  872. this.set('stopChecking', true);
  873. this.set('isJDKWarningsLoaded', true);
  874. this.set('isHostsWarningsLoaded', true);
  875. },
  876. getHostCheckSuccess: function(response) {
  877. if (!App.get('testMode')) {
  878. this.set("requestId", response.Requests.id);
  879. }
  880. this.getHostCheckTasks();
  881. },
  882. /**
  883. * generates data for reuest to perform check
  884. * @param {string} checkExecuteList - for now supported:
  885. * <code>"last_agent_env_check"<code>
  886. * <code>"host_resolution_check"<code>
  887. * @param {boolean} addHostsParameter - define whether add hosts parameter to RequestInfo
  888. * @return {object|null}
  889. * @method getDataForCheckRequest
  890. */
  891. getDataForCheckRequest: function (checkExecuteList, addHostsParameter) {
  892. var newHosts = this.get('bootHosts').filterProperty('bootStatus', 'REGISTERED').getEach('name');
  893. var hosts = this.get('isAddHostWizard') ? [].concat.apply([], App.MasterComponent.find().mapProperty('hostNames')).concat(newHosts).uniq() : newHosts;
  894. hosts = hosts.join(',');
  895. if (hosts.length == 0) return null;
  896. var jdk_location = App.router.get('clusterController.ambariProperties.jdk_location');
  897. var RequestInfo = {
  898. "action": "check_host",
  899. "context": "Check host",
  900. "parameters": {
  901. "check_execute_list": checkExecuteList,
  902. "jdk_location" : jdk_location,
  903. "threshold": "20"
  904. }
  905. };
  906. if (addHostsParameter) {
  907. RequestInfo.parameters.hosts = hosts;
  908. }
  909. var resource_filters = {
  910. "hosts": hosts
  911. };
  912. return {
  913. RequestInfo: RequestInfo,
  914. resource_filters: resource_filters
  915. }
  916. },
  917. /**
  918. * send request to ceate tasks for performing hosts checks
  919. * @params {object} data
  920. * {
  921. * RequestInfo: {
  922. * "action": {string},
  923. * "context": {string},
  924. * "parameters": {
  925. * "check_execute_list": {string},
  926. * "jdk_location" : {string},
  927. * "threshold": {string}
  928. * "hosts": {string|undefined}
  929. * },
  930. * resource_filters: {
  931. * "hosts": {string}
  932. * }
  933. * }
  934. * @returns {$.ajax}
  935. * @method requestToPerformHostCheck
  936. */
  937. requestToPerformHostCheck: function(data) {
  938. return App.ajax.send({
  939. name: 'preinstalled.checks',
  940. sender: this,
  941. data: {
  942. RequestInfo: data.RequestInfo,
  943. resource_filters: data.resource_filters
  944. },
  945. success: "getHostCheckSuccess",
  946. error: "getHostCheckError"
  947. })
  948. },
  949. /**
  950. * send ajax request to get all tasks
  951. * @method getHostCheckTasks
  952. */
  953. getHostCheckTasks: function () {
  954. var self = this;
  955. var requestId = this.get("requestId");
  956. var checker = setTimeout(function () {
  957. if (self.get('stopChecking') == true) {
  958. clearTimeout(checker);
  959. } else {
  960. App.ajax.send({
  961. name: 'preinstalled.checks.tasks',
  962. sender: self,
  963. data: {
  964. requestId: requestId
  965. },
  966. success: 'getHostCheckTasksSuccess',
  967. error: 'getHostCheckTasksError'
  968. });
  969. }
  970. }, 1000);
  971. },
  972. /**
  973. * add warnings to host warning popup if needed
  974. * @param data {Object} - json
  975. * @method getHostCheckTasksSuccess
  976. */
  977. getHostCheckTasksSuccess: function (data) {
  978. console.log('checking attempt...');
  979. if (!data) {
  980. console.warn("Error: jsonData is null");
  981. return;
  982. }
  983. if (["FAILED", "COMPLETED", "TIMEDOUT"].contains(data.Requests.request_status)) {
  984. if (data.Requests.inputs.indexOf("last_agent_env_check") != -1) {
  985. this.set('stopChecking', true);
  986. this.set('hostsPackagesData', data.tasks.map(function (task) {
  987. var installed_packages = Em.get(task, 'Tasks.structured_out.installed_packages');
  988. return {
  989. hostName: Em.get(task, 'Tasks.host_name'),
  990. transparentHugePage: Em.get(task, 'Tasks.structured_out.transparentHugePage.message'),
  991. installedPackages: installed_packages ? installed_packages : []
  992. };
  993. }));
  994. this.getHostInfo();
  995. } else if (data.Requests.inputs.indexOf("host_resolution_check") != -1) {
  996. this.parseHostNameResolution(data);
  997. this.getGeneralHostCheck();
  998. }
  999. } else {
  1000. this.getHostCheckTasks();
  1001. }
  1002. },
  1003. /**
  1004. * parse warnings for host names resolution only
  1005. * @param {object} data
  1006. * @method parseHostNameResolution
  1007. */
  1008. parseHostNameResolution: function (data) {
  1009. if (!data) {
  1010. console.warn("Error: jsonData is null");
  1011. return;
  1012. }
  1013. data.tasks.forEach(function (task) {
  1014. var name = Em.I18n.t('installer.step3.hostWarningsPopup.resolution.validation.error');
  1015. var hostInfo = this.get("hostCheckWarnings").findProperty('name', name);
  1016. if (["FAILED", "COMPLETED", "TIMEDOUT"].contains(task.Tasks.status)) {
  1017. if (task.Tasks.status == "COMPLETED" && Em.get(task, "Tasks.structured_out.host_resolution_check.failed_count") != 0) {
  1018. var targetHostName = Em.get(task, "Tasks.host_name");
  1019. var relatedHostNames = Em.get(task, "Tasks.structured_out.host_resolution_check.failures")
  1020. ? Em.get(task, "Tasks.structured_out.host_resolution_check.failures").mapProperty('host') : [];
  1021. var contextMessage = Em.I18n.t('installer.step3.hostWarningsPopup.resolution.validation.context').format(targetHostName, relatedHostNames.length + ' ' + Em.I18n.t('installer.step3.hostWarningsPopup.host' + (relatedHostNames.length == 1 ? '' : 's')));
  1022. var contextMessageLong = Em.I18n.t('installer.step3.hostWarningsPopup.resolution.validation.context').format(targetHostName, relatedHostNames.join(', '));
  1023. if (!hostInfo) {
  1024. hostInfo = {
  1025. name: name,
  1026. hosts: [contextMessage],
  1027. hostsLong: [contextMessageLong],
  1028. hostsNames: [targetHostName],
  1029. onSingleHost: true
  1030. };
  1031. this.get("hostCheckWarnings").push(hostInfo);
  1032. } else {
  1033. if (!hostInfo.hostsNames.contains(targetHostName)) {
  1034. hostInfo.hosts.push(contextMessage);
  1035. hostInfo.hostsLong.push(contextMessageLong);
  1036. hostInfo.hostsNames.push(targetHostName);
  1037. hostInfo.onSingleHost = false;
  1038. }
  1039. }
  1040. }
  1041. }
  1042. }, this);
  1043. },
  1044. getHostCheckError: function() {
  1045. this.getHostInfo();
  1046. },
  1047. stopChecking: false,
  1048. /**
  1049. * @method getHostCheckTasksError
  1050. */
  1051. getHostCheckTasksError: function() {
  1052. console.warn("failed to cheek hostName resolution");
  1053. this.set('stopChecking', true);
  1054. },
  1055. /**
  1056. * Success-callback for hosts info request
  1057. * @param {object} jsonData
  1058. * @method getHostInfoSuccessCallback
  1059. */
  1060. getHostInfoSuccessCallback: function (jsonData) {
  1061. var hosts = this.get('bootHosts'),
  1062. self = this,
  1063. repoWarnings = [], hostsRepoNames = [], hostsContext = [],
  1064. diskWarnings = [], hostsDiskContext = [], hostsDiskNames = [],
  1065. thpWarnings = [], thpContext = [], thpHostsNames = [];
  1066. // parse host checks warning
  1067. this.parseWarnings(jsonData);
  1068. this.set('isHostsWarningsLoaded', true);
  1069. hosts.forEach(function (_host) {
  1070. var host = (App.get('testMode')) ? jsonData.items[0] : jsonData.items.findProperty('Hosts.host_name', _host.name);
  1071. if (App.get('skipBootstrap')) {
  1072. self._setHostDataWithSkipBootstrap(_host);
  1073. }
  1074. else {
  1075. if (host) {
  1076. self._setHostDataFromLoadedHostInfo(_host, host);
  1077. var host_name = Em.get(host, 'Hosts.host_name');
  1078. var context = self.checkHostOSType(host.Hosts.os_family, host_name);
  1079. if (context) {
  1080. hostsContext.push(context);
  1081. hostsRepoNames.push(host_name);
  1082. }
  1083. var diskContext = self.checkHostDiskSpace(host_name, host.Hosts.disk_info);
  1084. if (diskContext) {
  1085. hostsDiskContext.push(diskContext);
  1086. hostsDiskNames.push(host_name);
  1087. }
  1088. // "Transparent Huge Pages" check
  1089. var _hostPackagesData = self.get('hostsPackagesData').findProperty('hostName', host.Hosts.host_name);
  1090. if (_hostPackagesData) {
  1091. var transparentHugePage = _hostPackagesData.transparentHugePage;
  1092. context = self.checkTHP(host_name, transparentHugePage);
  1093. } else {
  1094. context = self.checkTHP(host_name, Em.get(host, 'Hosts.last_agent_env.transparentHugePage'));
  1095. }
  1096. if (context) {
  1097. thpContext.push(context);
  1098. thpHostsNames.push(host_name);
  1099. }
  1100. }
  1101. }
  1102. });
  1103. if (hostsContext.length > 0) { // repository warning exist
  1104. repoWarnings.push({
  1105. name: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.name'),
  1106. hosts: hostsContext,
  1107. hostsLong: hostsContext,
  1108. hostsNames: hostsRepoNames,
  1109. category: 'repositories',
  1110. onSingleHost: false
  1111. });
  1112. }
  1113. if (hostsDiskContext.length > 0) { // disk space warning exist
  1114. diskWarnings.push({
  1115. name: Em.I18n.t('installer.step3.hostWarningsPopup.disk.name'),
  1116. hosts: hostsDiskContext,
  1117. hostsLong: hostsDiskContext,
  1118. hostsNames: hostsDiskNames,
  1119. category: 'disk',
  1120. onSingleHost: false
  1121. });
  1122. }
  1123. if (thpContext.length > 0) { // THP warning existed
  1124. thpWarnings.push({
  1125. name: Em.I18n.t('installer.step3.hostWarningsPopup.thp.name'),
  1126. hosts: thpContext,
  1127. hostsLong: thpContext,
  1128. hostsNames: thpHostsNames,
  1129. category: 'thp',
  1130. onSingleHost: false
  1131. });
  1132. }
  1133. this.set('repoCategoryWarnings', repoWarnings);
  1134. this.set('diskCategoryWarnings', diskWarnings);
  1135. this.set('thpCategoryWarnings', thpWarnings);
  1136. this.stopRegistration();
  1137. },
  1138. /**
  1139. * Set metrics to host object
  1140. * Used when <code>App.skipBootstrap</code> is true
  1141. * @param {Ember.Object} host
  1142. * @returns {object}
  1143. * @private
  1144. * @methos _setHostDataWithSkipBootstrap
  1145. */
  1146. _setHostDataWithSkipBootstrap: function(host) {
  1147. host.set('cpu', 2);
  1148. host.set('memory', ((parseInt(2000000))).toFixed(2));
  1149. host.set('disk_info', [
  1150. {"mountpoint": "/", "type": "ext4"},
  1151. {"mountpoint": "/grid/0", "type": "ext4"},
  1152. {"mountpoint": "/grid/1", "type": "ext4"},
  1153. {"mountpoint": "/grid/2", "type": "ext4"}
  1154. ]);
  1155. return host;
  1156. },
  1157. /**
  1158. * Set loaded metrics to host object
  1159. * @param {object} host
  1160. * @param {object} hostInfo
  1161. * @returns {object}
  1162. * @method _setHostDataFromLoadedHostInfo
  1163. * @private
  1164. */
  1165. _setHostDataFromLoadedHostInfo: function(host, hostInfo) {
  1166. host.set('cpu', Em.get(hostInfo, 'Hosts.cpu_count'));
  1167. host.set('memory', ((parseInt(Em.get(hostInfo, 'Hosts.total_mem')))).toFixed(2));
  1168. host.set('disk_info', Em.get(hostInfo, 'Hosts.disk_info').filter(function (h) {
  1169. return h.mountpoint != "/boot"
  1170. }));
  1171. host.set('os_type', Em.get(hostInfo, 'Hosts.os_type'));
  1172. host.set('os_family', Em.get(hostInfo, 'Hosts.os_family'));
  1173. host.set('os_arch', Em.get(hostInfo, 'Hosts.os_arch'));
  1174. host.set('ip', Em.get(hostInfo, 'Hosts.ip'));
  1175. return host;
  1176. },
  1177. /**
  1178. * Error-callback for hosts info request
  1179. * @method getHostInfoErrorCallback
  1180. */
  1181. getHostInfoErrorCallback: function () {
  1182. console.log('INFO: Getting host information(cpu_count and total_mem) from the server failed');
  1183. this.set('isHostsWarningsLoaded', true);
  1184. this.registerErrPopup(Em.I18n.t('installer.step3.hostInformation.popup.header'), Em.I18n.t('installer.step3.hostInformation.popup.body'));
  1185. },
  1186. /**
  1187. * Enable or disable submit/retry buttons according to hosts boot statuses
  1188. * @method stopRegistration
  1189. */
  1190. stopRegistration: function () {
  1191. this.set('isSubmitDisabled', !this.get('bootHosts').someProperty('bootStatus', 'REGISTERED'));
  1192. },
  1193. /**
  1194. * Check if the 'Transparent Huge Pages' enabled.
  1195. * @param {string} transparentHugePage
  1196. * @param {string} hostName
  1197. * @return {string} error-message or empty string
  1198. * @method checkTHP
  1199. */
  1200. checkTHP: function (hostName, transparentHugePage) {
  1201. if (transparentHugePage == "always") {
  1202. console.log('WARNING: Transparent Huge Page enabled on host: '+ hostName);
  1203. return Em.I18n.t('installer.step3.hostWarningsPopup.thp.context').format(hostName);
  1204. } else {
  1205. return '';
  1206. }
  1207. },
  1208. /**
  1209. * Check if the customized os group contains the registered host os type. If not the repo on that host is invalid.
  1210. * @param {string} osType
  1211. * @param {string} hostName
  1212. * @return {string} error-message or empty string
  1213. * @method checkHostOSType
  1214. */
  1215. checkHostOSType: function (osFamily, hostName) {
  1216. if (this.get('content.stacks')) {
  1217. var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
  1218. var selectedOS = [];
  1219. var isValid = false;
  1220. if (selectedStack && selectedStack.get('operatingSystems')) {
  1221. selectedStack.get('operatingSystems').filterProperty('isSelected', true).forEach(function (os) {
  1222. selectedOS.pushObject(os.get('osType'));
  1223. if (os.get('osType') === osFamily) {
  1224. isValid = true;
  1225. }
  1226. });
  1227. }
  1228. if (isValid) {
  1229. return '';
  1230. } else {
  1231. console.log('WARNING: Getting host os type does NOT match the user selected os group in step1. ' +
  1232. 'Host Name: ' + hostName + '. Host os type:' + osFamily + '. Selected group:' + selectedOS.uniq());
  1233. return Em.I18n.t('installer.step3.hostWarningsPopup.repositories.context').format(hostName, osFamily, selectedOS.uniq());
  1234. }
  1235. } else {
  1236. return '';
  1237. }
  1238. },
  1239. /**
  1240. * Check if current host has enough free disk usage.
  1241. * @param {string} hostName
  1242. * @param {object} diskInfo
  1243. * @return {string} error-message or empty string
  1244. * @method checkHostDiskSpace
  1245. */
  1246. checkHostDiskSpace: function (hostName, diskInfo) {
  1247. var minFreeRootSpace = App.minDiskSpace * 1024 * 1024; //in kilobyte
  1248. var minFreeUsrLibSpace = App.minDiskSpaceUsrLib * 1024 * 1024; //in kilobyte
  1249. var warningString = '';
  1250. diskInfo.forEach(function (info) {
  1251. switch (info.mountpoint) {
  1252. case '/':
  1253. warningString = info.available < minFreeRootSpace ?
  1254. Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpace + 'GB', info.mountpoint) + ' ' + warningString :
  1255. warningString;
  1256. break;
  1257. case '/usr':
  1258. case '/usr/lib':
  1259. warningString = info.available < minFreeUsrLibSpace ?
  1260. Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpaceUsrLib + 'GB', info.mountpoint) + ' ' + warningString :
  1261. warningString;
  1262. break;
  1263. default:
  1264. break;
  1265. }
  1266. });
  1267. if (warningString) {
  1268. console.log('WARNING: Getting host free disk space. ' + 'Host Name: ' + hostName);
  1269. return Em.I18n.t('installer.step3.hostWarningsPopup.disk.context1').format(hostName) + ' ' + warningString;
  1270. } else {
  1271. return '';
  1272. }
  1273. },
  1274. /**
  1275. * Submit-click handler
  1276. * @return {App.ModalPopup|null}
  1277. * @method submit
  1278. */
  1279. submit: function () {
  1280. var self = this;
  1281. if (this.get('isHostHaveWarnings')) {
  1282. return App.showConfirmationPopup(
  1283. function () {
  1284. self.set('confirmedHosts', self.get('bootHosts'));
  1285. App.router.send('next');
  1286. },
  1287. Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
  1288. }
  1289. else {
  1290. this.set('confirmedHosts', this.get('bootHosts'));
  1291. App.router.send('next');
  1292. }
  1293. return null;
  1294. },
  1295. /**
  1296. * Show popup with host log
  1297. * @param {object} event
  1298. * @return {App.ModalPopup}
  1299. */
  1300. hostLogPopup: function (event) {
  1301. var host = event.context;
  1302. return App.ModalPopup.show({
  1303. header: Em.I18n.t('installer.step3.hostLog.popup.header').format(host.get('name')),
  1304. secondary: null,
  1305. host: host,
  1306. bodyClass: App.WizardStep3HostLogPopupBody
  1307. });
  1308. },
  1309. /**
  1310. * Check warnings from server and put it in parsing
  1311. * @method rerunChecks
  1312. */
  1313. rerunChecks: function () {
  1314. var self = this;
  1315. var currentProgress = 0;
  1316. this.getHostNameResolution();
  1317. this.set('stopChecking', false);
  1318. this.getGeneralHostCheck();
  1319. this.checkHostJDK();
  1320. var interval = setInterval(function () {
  1321. currentProgress += 100000 / self.get('warningsTimeInterval');
  1322. if (currentProgress < 100) {
  1323. self.set('checksUpdateProgress', currentProgress);
  1324. } else {
  1325. clearInterval(interval);
  1326. App.ajax.send({
  1327. name: 'wizard.step3.rerun_checks',
  1328. sender: self,
  1329. success: 'rerunChecksSuccessCallback',
  1330. error: 'rerunChecksErrorCallback'
  1331. });
  1332. }
  1333. }, 1000);
  1334. },
  1335. /**
  1336. * Success-callback for rerun request
  1337. * @param {object} data
  1338. * @method rerunChecksSuccessCallback
  1339. */
  1340. rerunChecksSuccessCallback: function (data) {
  1341. this.set('checksUpdateProgress', 100);
  1342. this.set('checksUpdateStatus', 'SUCCESS');
  1343. this.parseWarnings(data);
  1344. },
  1345. /**
  1346. * Error-callback for rerun request
  1347. * @method rerunChecksErrorCallback
  1348. */
  1349. rerunChecksErrorCallback: function () {
  1350. this.set('checksUpdateProgress', 100);
  1351. this.set('checksUpdateStatus', 'FAILED');
  1352. console.log('INFO: Getting host information(last_agent_env) from the server failed');
  1353. },
  1354. /**
  1355. * Filter data for warnings parse
  1356. * is data from host in bootStrap
  1357. * @param {object} data
  1358. * @return {Object}
  1359. * @method filterBootHosts
  1360. */
  1361. filterBootHosts: function (data) {
  1362. var bootHostNames = {};
  1363. this.get('bootHosts').forEach(function (bootHost) {
  1364. bootHostNames[bootHost.get('name')] = true;
  1365. });
  1366. var filteredData = {
  1367. href: data.href,
  1368. items: []
  1369. };
  1370. data.items.forEach(function (host) {
  1371. if (bootHostNames[host.Hosts.host_name]) {
  1372. filteredData.items.push(host);
  1373. }
  1374. });
  1375. return filteredData;
  1376. },
  1377. /**
  1378. * Parse warnings data for each host and total
  1379. * @param {object} data
  1380. * @method parseWarnings
  1381. */
  1382. parseWarnings: function (data) {
  1383. data = App.get('testMode') ? data : this.filterBootHosts(data);
  1384. var warnings = [];
  1385. var warning;
  1386. var hosts = [];
  1387. var warningCategories = {
  1388. fileFoldersWarnings: {},
  1389. packagesWarnings: {},
  1390. processesWarnings: {},
  1391. servicesWarnings: {},
  1392. usersWarnings: {},
  1393. alternativeWarnings: {}
  1394. };
  1395. var hostsPackagesData = this.get('hostsPackagesData');
  1396. data.items.sortPropertyLight('Hosts.host_name').forEach(function (_host) {
  1397. var host = {
  1398. name: _host.Hosts.host_name,
  1399. warnings: []
  1400. };
  1401. if (!_host.Hosts.last_agent_env) {
  1402. // in some unusual circumstances when last_agent_env is not available from the _host,
  1403. // skip the _host and proceed to process the rest of the hosts.
  1404. console.log("last_agent_env is missing for " + _host.Hosts.host_name + ". Skipping _host check.");
  1405. return;
  1406. }
  1407. //parse all directories and files warnings for host
  1408. //todo: to be removed after check in new API
  1409. var stackFoldersAndFiles = _host.Hosts.last_agent_env.stackFoldersAndFiles || [];
  1410. stackFoldersAndFiles.forEach(function (path) {
  1411. warning = warningCategories.fileFoldersWarnings[path.name];
  1412. if (warning) {
  1413. warning.hosts.push(_host.Hosts.host_name);
  1414. warning.hostsLong.push(_host.Hosts.host_name);
  1415. warning.onSingleHost = false;
  1416. } else {
  1417. warningCategories.fileFoldersWarnings[path.name] = warning = {
  1418. name: path.name,
  1419. hosts: [_host.Hosts.host_name],
  1420. hostsLong: [_host.Hosts.host_name],
  1421. category: 'fileFolders',
  1422. onSingleHost: true
  1423. };
  1424. }
  1425. host.warnings.push(warning);
  1426. }, this);
  1427. //parse all package warnings for host
  1428. var _hostPackagesData = hostsPackagesData.findProperty('hostName', _host.Hosts.host_name);
  1429. if (_hostPackagesData) {
  1430. _hostPackagesData.installedPackages.forEach(function (_package) {
  1431. warning = warningCategories.packagesWarnings[_package.name];
  1432. if (warning) {
  1433. warning.hosts.push(_host.Hosts.host_name);
  1434. warning.hostsLong.push(_host.Hosts.host_name);
  1435. warning.version = _package.version;
  1436. warning.onSingleHost = false;
  1437. } else {
  1438. warningCategories.packagesWarnings[_package.name] = warning = {
  1439. name: _package.name,
  1440. version: _package.version,
  1441. hosts: [_host.Hosts.host_name],
  1442. hostsLong: [_host.Hosts.host_name],
  1443. category: 'packages',
  1444. onSingleHost: true
  1445. };
  1446. }
  1447. host.warnings.push(warning);
  1448. }, this);
  1449. }
  1450. //parse all process warnings for host
  1451. //todo: to be removed after check in new API
  1452. var javaProcs = _host.Hosts.last_agent_env.hostHealth ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs : _host.Hosts.last_agent_env.javaProcs;
  1453. if (javaProcs) {
  1454. javaProcs.forEach(function (process) {
  1455. warning = warningCategories.processesWarnings[process.pid];
  1456. if (warning) {
  1457. warning.hosts.push(_host.Hosts.host_name);
  1458. warning.hostsLong.push(_host.Hosts.host_name);
  1459. warning.onSingleHost = false;
  1460. } else {
  1461. warningCategories.processesWarnings[process.pid] = warning = {
  1462. name: (process.command.substr(0, 35) + '...'),
  1463. hosts: [_host.Hosts.host_name],
  1464. hostsLong: [_host.Hosts.host_name],
  1465. category: 'processes',
  1466. user: process.user,
  1467. pid: process.pid,
  1468. command: '<table><tr><td style="word-break: break-all;">' +
  1469. ((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
  1470. '<p style="text-align: center">................</p>' +
  1471. '...' + process.command.substr(-230)) + '</td></tr></table>',
  1472. onSingleHost: true
  1473. };
  1474. }
  1475. host.warnings.push(warning);
  1476. }, this);
  1477. }
  1478. //parse all service warnings for host
  1479. //todo: to be removed after check in new API
  1480. if (_host.Hosts.last_agent_env.hostHealth && _host.Hosts.last_agent_env.hostHealth.liveServices) {
  1481. _host.Hosts.last_agent_env.hostHealth.liveServices.forEach(function (service) {
  1482. if (service.status === 'Unhealthy') {
  1483. warning = warningCategories.servicesWarnings[service.name];
  1484. if (warning) {
  1485. warning.hosts.push(_host.Hosts.host_name);
  1486. warning.hostsLong.push(_host.Hosts.host_name);
  1487. warning.onSingleHost = false;
  1488. } else {
  1489. warningCategories.servicesWarnings[service.name] = warning = {
  1490. name: service.name,
  1491. hosts: [_host.Hosts.host_name],
  1492. hostsLong: [_host.Hosts.host_name],
  1493. category: 'services',
  1494. onSingleHost: true
  1495. };
  1496. }
  1497. host.warnings.push(warning);
  1498. }
  1499. }, this);
  1500. }
  1501. //parse all user warnings for host
  1502. //todo: to be removed after check in new API
  1503. if (_host.Hosts.last_agent_env.existingUsers) {
  1504. _host.Hosts.last_agent_env.existingUsers.forEach(function (user) {
  1505. warning = warningCategories.usersWarnings[user.userName];
  1506. if (warning) {
  1507. warning.hosts.push(_host.Hosts.host_name);
  1508. warning.hostsLong.push(_host.Hosts.host_name);
  1509. warning.onSingleHost = false;
  1510. } else {
  1511. warningCategories.usersWarnings[user.userName] = warning = {
  1512. name: user.userName,
  1513. hosts: [_host.Hosts.host_name],
  1514. hostsLong: [_host.Hosts.host_name],
  1515. category: 'users',
  1516. onSingleHost: true
  1517. };
  1518. }
  1519. host.warnings.push(warning);
  1520. }, this);
  1521. }
  1522. //parse misc warnings for host
  1523. var umask = _host.Hosts.last_agent_env.umask;
  1524. if (umask && umask > 23) {
  1525. warning = warnings.filterProperty('category', 'misc').findProperty('name', umask);
  1526. if (warning) {
  1527. warning.hosts.push(_host.Hosts.host_name);
  1528. warning.hostsLong.push(_host.Hosts.host_name);
  1529. warning.onSingleHost = false;
  1530. } else {
  1531. warning = {
  1532. name: umask,
  1533. hosts: [_host.Hosts.host_name],
  1534. hostsLong: [_host.Hosts.host_name],
  1535. category: 'misc',
  1536. onSingleHost: true
  1537. };
  1538. warnings.push(warning);
  1539. }
  1540. host.warnings.push(warning);
  1541. }
  1542. var firewallRunning = _host.Hosts.last_agent_env.firewallRunning;
  1543. if (firewallRunning !== null && firewallRunning) {
  1544. var name = _host.Hosts.last_agent_env.firewallName + " Running";
  1545. warning = warnings.filterProperty('category', 'firewall').findProperty('name', name);
  1546. if (warning) {
  1547. warning.hosts.push(_host.Hosts.host_name);
  1548. warning.hostsLong.push(_host.Hosts.host_name);
  1549. warning.onSingleHost = false;
  1550. } else {
  1551. warning = {
  1552. name: name,
  1553. hosts: [_host.Hosts.host_name],
  1554. hostsLong: [_host.Hosts.host_name],
  1555. category: 'firewall',
  1556. onSingleHost: true
  1557. };
  1558. warnings.push(warning);
  1559. }
  1560. host.warnings.push(warning);
  1561. }
  1562. if (_host.Hosts.last_agent_env.alternatives) {
  1563. _host.Hosts.last_agent_env.alternatives.forEach(function (alternative) {
  1564. warning = warningCategories.alternativeWarnings[alternative.name];
  1565. if (warning) {
  1566. warning.hosts.push(_host.Hosts.host_name);
  1567. warning.hostsLong.push(_host.Hosts.host_name);
  1568. warning.onSingleHost = false;
  1569. } else {
  1570. warningCategories.alternativeWarnings[alternative.name] = warning = {
  1571. name: alternative.name,
  1572. target: alternative.target,
  1573. hosts: [_host.Hosts.host_name],
  1574. hostsLong: [_host.Hosts.host_name],
  1575. category: 'alternatives',
  1576. onSingleHost: true
  1577. };
  1578. }
  1579. host.warnings.push(warning);
  1580. }, this);
  1581. }
  1582. if (_host.Hosts.last_agent_env.reverseLookup === false) {
  1583. var name = Em.I18n.t('installer.step3.hostWarningsPopup.reverseLookup.name');
  1584. warning = warnings.filterProperty('category', 'reverseLookup').findProperty('name', name);
  1585. if (warning) {
  1586. warning.hosts.push(_host.Hosts.host_name);
  1587. warning.hostsLong.push(_host.Hosts.host_name);
  1588. warning.onSingleHost = false;
  1589. } else {
  1590. warning = {
  1591. name: name,
  1592. hosts: [_host.Hosts.host_name],
  1593. hostsLong: [_host.Hosts.host_name],
  1594. category: 'reverseLookup',
  1595. onSingleHost: true
  1596. };
  1597. warnings.push(warning);
  1598. }
  1599. host.warnings.push(warning);
  1600. }
  1601. hosts.push(host);
  1602. }, this);
  1603. for (var categoryId in warningCategories) {
  1604. var category = warningCategories[categoryId];
  1605. for (var warningId in category) {
  1606. warnings.push(category[warningId]);
  1607. }
  1608. }
  1609. hosts.unshift({
  1610. name: 'All Hosts',
  1611. warnings: warnings
  1612. });
  1613. this.set('warnings', warnings);
  1614. this.set('warningsByHost', hosts);
  1615. },
  1616. /**
  1617. * Open popup that contain hosts' warnings
  1618. * @return {App.ModalPopup}
  1619. * @method hostWarningsPopup
  1620. */
  1621. hostWarningsPopup: function () {
  1622. var self = this;
  1623. return App.ModalPopup.show({
  1624. header: Em.I18n.t('installer.step3.warnings.popup.header'),
  1625. secondary: Em.I18n.t('installer.step3.hostWarningsPopup.rerunChecks'),
  1626. primary: Em.I18n.t('common.close'),
  1627. autoHeight: false,
  1628. onPrimary: function () {
  1629. self.set('checksUpdateStatus', null);
  1630. this.hide();
  1631. },
  1632. onClose: function () {
  1633. self.set('checksUpdateStatus', null);
  1634. this.hide();
  1635. },
  1636. onSecondary: function () {
  1637. self.rerunChecks();
  1638. },
  1639. didInsertElement: function () {
  1640. this._super();
  1641. this.fitHeight();
  1642. },
  1643. footerClass: App.WizardStep3HostWarningPopupFooter,
  1644. bodyClass: App.WizardStep3HostWarningPopupBody
  1645. });
  1646. },
  1647. /**
  1648. * Show popup with registered hosts
  1649. * @return {App.ModalPopup}
  1650. * @method registeredHostsPopup
  1651. */
  1652. registeredHostsPopup: function () {
  1653. var self = this;
  1654. return App.ModalPopup.show({
  1655. header: Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('registeredHosts').length),
  1656. secondary: null,
  1657. bodyClass: Em.View.extend({
  1658. templateName: require('templates/wizard/step3/step3_registered_hosts_popup'),
  1659. message: Em.I18n.t('installer.step3.registeredHostsPopup'),
  1660. registeredHosts: self.get('registeredHosts')
  1661. })
  1662. })
  1663. }
  1664. });