step3_controller.js 58 KB

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