step3_controller.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  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({
  22. name: 'wizardStep3Controller',
  23. hosts: [],
  24. content: [],
  25. bootHosts: [],
  26. registeredHosts: [],
  27. repoCategoryWarnings: [],
  28. diskCategoryWarnings: [],
  29. registrationStartedAt: null,
  30. requestId: 0,
  31. hostCheckWarnings: [],
  32. /**
  33. * Timeout for registration
  34. * Based on <code>installOptions.manualInstall</code>
  35. * @type {number}
  36. */
  37. registrationTimeoutSecs: function () {
  38. return this.get('content.installOptions.manualInstall') ? 15 : 120;
  39. }.property('content.installOptions.manualInstall'),
  40. /**
  41. * Bootstrap calls are stopped
  42. * @type {bool}
  43. */
  44. stopBootstrap: false,
  45. /**
  46. * is Submit button disabled
  47. * @type {bool}
  48. */
  49. isSubmitDisabled: true,
  50. /**
  51. * is Retry button disabled
  52. * @type {bool}
  53. */
  54. isRetryDisabled: true,
  55. /**
  56. * @type {bool}
  57. */
  58. isLoaded: false,
  59. /**
  60. * Polls count
  61. * @type {number}
  62. */
  63. numPolls: 0,
  64. /**
  65. * Is hosts registration in progress
  66. * @type {bool}
  67. */
  68. isRegistrationInProgress: true,
  69. /**
  70. * Are some registered hosts which are not added by user
  71. * @type {bool}
  72. */
  73. hasMoreRegisteredHosts: false,
  74. /**
  75. * List of installed hostnames
  76. * @type {string[]}
  77. */
  78. hostsInCluster: function () {
  79. return App.Host.find().getEach('hostName');
  80. }.property().volatile(),
  81. /**
  82. * All hosts warnings
  83. * @type {object[]}
  84. */
  85. warnings: [],
  86. /**
  87. * Warnings grouped by host
  88. * @type {Ember.Enumerable}
  89. */
  90. warningsByHost: [],
  91. /**
  92. * Timeout for "warning"-requests
  93. * @type {number}
  94. */
  95. warningsTimeInterval: 60000,
  96. /**
  97. * Are hosts warnings loaded
  98. * @type {bool}
  99. */
  100. isWarningsLoaded: false,
  101. /**
  102. * Check are hosts have any warnings
  103. * @type {bool}
  104. */
  105. isHostHaveWarnings: function () {
  106. return this.get('warnings.length') > 0;
  107. }.property('warnings'),
  108. /**
  109. * Should warnings-box be visible
  110. * @type {bool}
  111. */
  112. isWarningsBoxVisible: function () {
  113. return (App.testMode) ? true : !this.get('isRegistrationInProgress');
  114. }.property('isRegistrationInProgress'),
  115. /**
  116. * Progress value for "update hosts status" process
  117. * @type {number}
  118. */
  119. checksUpdateProgress: 0,
  120. /**
  121. *
  122. * @type {object}
  123. */
  124. checksUpdateStatus: null,
  125. /**
  126. *
  127. * @method navigateStep
  128. */
  129. navigateStep: function () {
  130. if (this.get('isLoaded')) {
  131. if (!this.get('content.installOptions.manualInstall')) {
  132. if (!this.get('wizardController').getDBProperty('bootStatus')) {
  133. this.startBootstrap();
  134. }
  135. } else {
  136. this.set('bootHosts', this.get('hosts'));
  137. if (App.get('testMode')) {
  138. this.startHostcheck();
  139. this.get('bootHosts').setEach('cpu', '2');
  140. this.get('bootHosts').setEach('memory', '2000000');
  141. this.set('isSubmitDisabled', false);
  142. } else {
  143. this.set('registrationStartedAt', null);
  144. this.startRegistration();
  145. }
  146. }
  147. }
  148. }.observes('isLoaded'),
  149. /**
  150. * Clear controller data
  151. * @method clearStep
  152. */
  153. clearStep: function () {
  154. this.set('stopBootstrap', false);
  155. this.set('hosts', []);
  156. this.get('bootHosts').clear();
  157. this.get('wizardController').setDBProperty('bootStatus', false);
  158. this.set('isSubmitDisabled', true);
  159. this.set('isRetryDisabled', true);
  160. },
  161. /**
  162. * Make basic init steps
  163. * @method loadStep
  164. */
  165. loadStep: function () {
  166. console.log("TRACE: Loading step3: Confirm Hosts");
  167. this.set('registrationStartedAt', null);
  168. this.set('isLoaded', false);
  169. this.disablePreviousSteps();
  170. this.clearStep();
  171. this.loadHosts();
  172. },
  173. /**
  174. * Loads the hostinfo from localStorage on the insertion of view. It's being called from view
  175. * @method loadHosts
  176. */
  177. loadHosts: function () {
  178. var hostsInfo = this.get('content.hosts');
  179. var hosts = [];
  180. var bootStatus = (this.get('content.installOptions.manualInstall')) ? 'DONE' : 'PENDING';
  181. if (App.testMode) {
  182. bootStatus = 'REGISTERED';
  183. }
  184. for (var index in hostsInfo) {
  185. if (hostsInfo.hasOwnProperty(index)) {
  186. hosts.pushObject(App.HostInfo.create({
  187. name: hostsInfo[index].name,
  188. bootStatus: bootStatus,
  189. isChecked: false
  190. }));
  191. }
  192. }
  193. this.set('hosts', hosts);
  194. this.set('isLoaded', true);
  195. },
  196. /**
  197. * Parses and updates the content based on bootstrap API response.
  198. * @return {bool} true if polling should continue (some hosts are in "RUNNING" state); false otherwise
  199. * @method parseHostInfo
  200. */
  201. parseHostInfo: function (hostsStatusFromServer) {
  202. hostsStatusFromServer.forEach(function (_hostStatus) {
  203. var host = this.get('bootHosts').findProperty('name', _hostStatus.hostName);
  204. // check if hostname extracted from REST API data matches any hostname in content
  205. // also, make sure that bootStatus modified by isHostsRegistered call does not get overwritten
  206. // since these calls are being made in parallel
  207. if (host && !['REGISTERED', 'REGISTERING'].contains(host.get('bootStatus'))) {
  208. host.set('bootStatus', _hostStatus.status);
  209. host.set('bootLog', _hostStatus.log);
  210. }
  211. }, this);
  212. // if the data rendered by REST API has hosts in "RUNNING" state, polling will continue
  213. return this.get('bootHosts').length != 0 && this.get('bootHosts').someProperty('bootStatus', 'RUNNING');
  214. },
  215. /**
  216. * Remove list of hosts
  217. * @param {Ember.Enumerable} hosts
  218. * @return {App.ModalPopup}
  219. * @method removeHosts
  220. */
  221. removeHosts: function (hosts) {
  222. var self = this;
  223. return App.showConfirmationPopup(function () {
  224. App.router.send('removeHosts', hosts);
  225. self.hosts.removeObjects(hosts);
  226. if (!self.hosts.length) {
  227. self.set('isSubmitDisabled', true);
  228. }
  229. }, Em.I18n.t('installer.step3.hosts.remove.popup.body'));
  230. },
  231. /**
  232. * Removes a single element on the trash icon click. Called from View
  233. * @param {object} hostInfo
  234. * @method removeHost
  235. */
  236. removeHost: function (hostInfo) {
  237. this.removeHosts([hostInfo]);
  238. },
  239. /**
  240. * Remove selected hosts (click-handler)
  241. * @return App.ModalPopup
  242. * @method removeSelectedHosts
  243. */
  244. removeSelectedHosts: function () {
  245. var selectedHosts = this.get('hosts').filterProperty('isChecked', true);
  246. selectedHosts.forEach(function (_hostInfo) {
  247. console.log('Removing: ' + _hostInfo.name);
  248. });
  249. return this.removeHosts(selectedHosts);
  250. },
  251. /**
  252. * Show popup with the list of hosts which are selected
  253. * @return App.ModalPopup
  254. * @method selectedHostsPopup
  255. */
  256. selectedHostsPopup: function () {
  257. var selectedHosts = this.get('hosts').filterProperty('isChecked').mapProperty('name');
  258. return App.ModalPopup.show({
  259. header: Em.I18n.t('installer.step3.selectedHosts.popup.header'),
  260. secondary: null,
  261. bodyClass: Em.View.extend({
  262. templateName: require('templates/common/items_list_popup'),
  263. items: selectedHosts,
  264. insertedItems: [],
  265. didInsertElement: function () {
  266. lazyloading.run({
  267. destination: this.get('insertedItems'),
  268. source: this.get('items'),
  269. context: this,
  270. initSize: 100,
  271. chunkSize: 500,
  272. delay: 100
  273. });
  274. }
  275. })
  276. });
  277. },
  278. /**
  279. * Retry one host {click-handler}
  280. * @param {object} hostInfo
  281. * @method retryHost
  282. */
  283. retryHost: function (hostInfo) {
  284. this.retryHosts([hostInfo]);
  285. },
  286. /**
  287. * Retry list of hosts
  288. * @param {object[]} hosts
  289. * @method retryHosts
  290. */
  291. retryHosts: function (hosts) {
  292. var self = this;
  293. var bootStrapData = JSON.stringify({
  294. 'verbose': true,
  295. 'sshKey': this.get('content.installOptions.sshKey'),
  296. 'hosts': hosts.mapProperty('name'),
  297. 'user': this.get('content.installOptions.sshUser')}
  298. );
  299. this.set('numPolls', 0);
  300. this.set('registrationStartedAt', null);
  301. if (this.get('content.installOptions.manualInstall')) {
  302. this.get('bootHosts').setEach('bootStatus', 'DONE');
  303. this.startRegistration();
  304. }
  305. else {
  306. App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
  307. self.set('content.installOptions.bootRequestId', requestId);
  308. self.doBootstrap();
  309. });
  310. }
  311. },
  312. /**
  313. * Retry selected hosts (click-handler)
  314. * @method retrySelectedHosts
  315. */
  316. retrySelectedHosts: function () {
  317. if (!this.get('isRetryDisabled')) {
  318. this.set('isRetryDisabled', true);
  319. var selectedHosts = this.get('bootHosts').filterProperty('bootStatus', 'FAILED');
  320. selectedHosts.forEach(function (_host) {
  321. _host.set('bootStatus', 'RUNNING');
  322. _host.set('bootLog', 'Retrying ...');
  323. }, this);
  324. this.retryHosts(selectedHosts);
  325. }
  326. },
  327. /**
  328. * Init bootstrap settings and start it
  329. * @method startBootstrap
  330. */
  331. startBootstrap: function () {
  332. //this.set('isSubmitDisabled', true); //TODO: uncomment after actual hookup
  333. this.set('numPolls', 0);
  334. this.set('registrationStartedAt', null);
  335. this.set('bootHosts', this.get('hosts'));
  336. this.doBootstrap();
  337. },
  338. /**
  339. * Update <code>isRegistrationInProgress</code> once
  340. * @method setRegistrationInProgressOnce
  341. */
  342. setRegistrationInProgressOnce: function () {
  343. Em.run.once(this, 'setRegistrationInProgress');
  344. }.observes('bootHosts.@each.bootStatus'),
  345. /**
  346. * Set <code>isRegistrationInProgress</code> value based on each host boot status
  347. * @method setRegistrationInProgress
  348. */
  349. setRegistrationInProgress: function () {
  350. var bootHosts = this.get('bootHosts');
  351. //if hosts aren't loaded yet then registration should be in progress
  352. var result = (bootHosts.length === 0 && !this.get('isLoaded'));
  353. for (var i = 0, l = bootHosts.length; i < l; i++) {
  354. if (bootHosts[i].get('bootStatus') !== 'REGISTERED' && bootHosts[i].get('bootStatus') !== 'FAILED') {
  355. result = true;
  356. break;
  357. }
  358. }
  359. this.set('isRegistrationInProgress', result);
  360. },
  361. /**
  362. * Disable wizard's previous steps (while registering)
  363. * @method disablePreviousSteps
  364. */
  365. disablePreviousSteps: function () {
  366. App.router.get('installerController.isStepDisabled').filter(function (step) {
  367. return step.step >= 0 && step.step <= 2;
  368. }).setEach('value', this.get('isRegistrationInProgress'));
  369. if (this.get('isRegistrationInProgress')) {
  370. this.set('isSubmitDisabled', true);
  371. }
  372. }.observes('isRegistrationInProgress'),
  373. /**
  374. * Do bootstrap calls
  375. * @method doBootstrap
  376. * @return {$.ajax|null}
  377. */
  378. doBootstrap: function () {
  379. if (this.get('stopBootstrap')) {
  380. return null;
  381. }
  382. this.incrementProperty('numPolls');
  383. return App.ajax.send({
  384. name: 'wizard.step3.bootstrap',
  385. sender: this,
  386. data: {
  387. bootRequestId: this.get('content.installOptions.bootRequestId'),
  388. numPolls: this.get('numPolls')
  389. },
  390. success: 'doBootstrapSuccessCallback'
  391. }).
  392. retry({
  393. times: App.maxRetries,
  394. timeout: App.timeout
  395. }).
  396. then(
  397. null,
  398. function () {
  399. App.showReloadPopup();
  400. console.log('Bootstrap failed');
  401. }
  402. );
  403. },
  404. /**
  405. * Success-callback for each boostrap request
  406. * @param {object} data
  407. * @method doBootstrapSuccessCallback
  408. */
  409. doBootstrapSuccessCallback: function (data) {
  410. var self = this;
  411. var pollingInterval = 3000;
  412. if (Em.isNone(data.hostsStatus)) {
  413. console.log('Invalid response, setting timeout');
  414. window.setTimeout(function () {
  415. self.doBootstrap()
  416. }, pollingInterval);
  417. } else {
  418. // in case of bootstrapping just one host, the server returns an object rather than an array, so
  419. // force into an array
  420. if (!(data.hostsStatus instanceof Array)) {
  421. data.hostsStatus = [ data.hostsStatus ];
  422. }
  423. console.log("TRACE: In success function for the GET bootstrap call");
  424. var keepPolling = this.parseHostInfo(data.hostsStatus);
  425. // Single host : if the only hostname is invalid (data.status == 'ERROR')
  426. // Multiple hosts : if one or more hostnames are invalid
  427. // following check will mark the bootStatus as 'FAILED' for the invalid hostname
  428. if (data.status == 'ERROR' || data.hostsStatus.length != this.get('bootHosts').length) {
  429. var hosts = this.get('bootHosts');
  430. for (var i = 0; i < hosts.length; i++) {
  431. var isValidHost = data.hostsStatus.someProperty('hostName', hosts[i].get('name'));
  432. if (hosts[i].get('bootStatus') !== 'REGISTERED') {
  433. if (!isValidHost) {
  434. hosts[i].set('bootStatus', 'FAILED');
  435. hosts[i].set('bootLog', Em.I18n.t('installer.step3.hosts.bootLog.failed'));
  436. }
  437. }
  438. }
  439. }
  440. if (data.status == 'ERROR' || data.hostsStatus.someProperty('status', 'DONE') || data.hostsStatus.someProperty('status', 'FAILED')) {
  441. // kicking off registration polls after at least one host has succeeded
  442. this.startRegistration();
  443. }
  444. if (keepPolling) {
  445. window.setTimeout(function () {
  446. self.doBootstrap()
  447. }, pollingInterval);
  448. }
  449. }
  450. },
  451. /**
  452. * Start hosts registration
  453. * @method startRegistration
  454. */
  455. startRegistration: function () {
  456. if (Em.isNone(this.get('registrationStartedAt'))) {
  457. this.set('registrationStartedAt', App.dateTime());
  458. console.log('registration started at ' + this.get('registrationStartedAt'));
  459. this.isHostsRegistered();
  460. }
  461. },
  462. /**
  463. * Do requests to check if hosts are already registered
  464. * @return {$.ajax|null}
  465. * @method isHostsRegistered
  466. */
  467. isHostsRegistered: function () {
  468. if (this.get('stopBootstrap')) {
  469. return null;
  470. }
  471. return App.ajax.send({
  472. name: 'wizard.step3.is_hosts_registered',
  473. sender: this,
  474. success: 'isHostsRegisteredSuccessCallback'
  475. }).
  476. retry({
  477. times: App.maxRetries,
  478. timeout: App.timeout
  479. }).
  480. then(
  481. null,
  482. function () {
  483. App.showReloadPopup();
  484. console.log('Error: Getting registered host information from the server');
  485. }
  486. );
  487. },
  488. /**
  489. * Success-callback for registered hosts request
  490. * @param {object} data
  491. * @method isHostsRegisteredSuccessCallback
  492. */
  493. isHostsRegisteredSuccessCallback: function (data) {
  494. console.log('registration attempt...');
  495. var hosts = this.get('bootHosts');
  496. var jsonData = data;
  497. if (!jsonData) {
  498. console.warn("Error: jsonData is null");
  499. return;
  500. }
  501. // keep polling until all hosts have registered/failed, or registrationTimeout seconds after the last host finished bootstrapping
  502. var stopPolling = true;
  503. hosts.forEach(function (_host, index) {
  504. // Change name of first host for test mode.
  505. if (App.testMode) {
  506. if (index == 0) {
  507. _host.set('name', 'localhost.localdomain');
  508. }
  509. }
  510. // actions to take depending on the host's current bootStatus
  511. // RUNNING - bootstrap is running; leave it alone
  512. // DONE - bootstrap is done; transition to REGISTERING
  513. // REGISTERING - bootstrap is done but has not registered; transition to REGISTERED if host found in polling API result
  514. // REGISTERED - bootstrap and registration is done; leave it alone
  515. // FAILED - either bootstrap or registration failed; leave it alone
  516. switch (_host.get('bootStatus')) {
  517. case 'DONE':
  518. _host.set('bootStatus', 'REGISTERING');
  519. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
  520. // update registration timestamp so that the timeout is computed from the last host that finished bootstrapping
  521. this.set('registrationStartedAt', App.dateTime());
  522. stopPolling = false;
  523. break;
  524. case 'REGISTERING':
  525. if (jsonData.items.someProperty('Hosts.host_name', _host.name)) {
  526. _host.set('bootStatus', 'REGISTERED');
  527. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
  528. } else {
  529. stopPolling = false;
  530. }
  531. break;
  532. case 'RUNNING':
  533. stopPolling = false;
  534. break;
  535. case 'REGISTERED':
  536. case 'FAILED':
  537. default:
  538. break;
  539. }
  540. }, this);
  541. if (stopPolling) {
  542. this.startHostcheck();
  543. }
  544. else {
  545. if (hosts.someProperty('bootStatus', 'RUNNING') || App.dateTime() - this.get('registrationStartedAt') < this.get('registrationTimeoutSecs') * 1000) {
  546. // we want to keep polling for registration status if any of the hosts are still bootstrapping (so we check for RUNNING).
  547. var self = this;
  548. window.setTimeout(function () {
  549. self.isHostsRegistered();
  550. }, 3000);
  551. }
  552. else {
  553. // registration timed out. mark all REGISTERING hosts to FAILED
  554. console.log('registration timed out');
  555. hosts.filterProperty('bootStatus', 'REGISTERING').forEach(function (_host) {
  556. _host.set('bootStatus', 'FAILED');
  557. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.failed'));
  558. });
  559. this.startHostcheck();
  560. }
  561. }
  562. },
  563. /**
  564. * Do request for all registered hosts
  565. * @return {$.ajax}
  566. * @method getAllRegisteredHosts
  567. */
  568. getAllRegisteredHosts: function () {
  569. return App.ajax.send({
  570. name: 'wizard.step3.is_hosts_registered',
  571. sender: this,
  572. success: 'getAllRegisteredHostsCallback'
  573. });
  574. }.observes('bootHosts'),
  575. /**
  576. * Success-callback for all registered hosts request
  577. * @param {object} hosts
  578. * @method getAllRegisteredHostsCallback
  579. */
  580. getAllRegisteredHostsCallback: function (hosts) {
  581. var registeredHosts = [];
  582. var hostsInCluster = this.get('hostsInCluster');
  583. var addedHosts = this.get('bootHosts').getEach('name');
  584. hosts.items.forEach(function (host) {
  585. if (!hostsInCluster.contains(host.Hosts.host_name) && !addedHosts.contains(host.Hosts.host_name)) {
  586. registeredHosts.push(host.Hosts.host_name);
  587. }
  588. });
  589. if (registeredHosts.length) {
  590. this.set('hasMoreRegisteredHosts', true);
  591. this.set('registeredHosts', registeredHosts);
  592. } else {
  593. this.set('hasMoreRegisteredHosts', false);
  594. this.set('registeredHosts', '');
  595. }
  596. },
  597. /**
  598. * Show popup with regitration error-message
  599. * @param {string} header
  600. * @param {string} message
  601. * @return {App.ModalPopup}
  602. * @method registerErrPopup
  603. */
  604. registerErrPopup: function (header, message) {
  605. return App.ModalPopup.show({
  606. header: header,
  607. secondary: false,
  608. bodyClass: Em.View.extend({
  609. template: Em.Handlebars.compile('<p>{{view.message}}</p>'),
  610. message: message
  611. })
  612. });
  613. },
  614. /**
  615. * Get disk info and cpu count of booted hosts from server
  616. * @return {$.ajax}
  617. * @method getHostInfo
  618. */
  619. getHostInfo: function () {
  620. this.set('isWarningsLoaded', false);
  621. return App.ajax.send({
  622. name: 'wizard.step3.host_info',
  623. sender: this,
  624. success: 'getHostInfoSuccessCallback',
  625. error: 'getHostInfoErrorCallback'
  626. });
  627. },
  628. startHostcheck: function() {
  629. this.set('isWarningsLoaded', false);
  630. this.getHostNameResolution();
  631. },
  632. getHostNameResolution: function () {
  633. var hosts = this.get('bootHosts').getEach('name').join(",");
  634. var RequestInfo = {
  635. "action": "check_host",
  636. "context": "Check host",
  637. "parameters": {
  638. "check_execute_list": "host_resolution_check",
  639. "hosts": hosts,
  640. "threshold": "20"
  641. }
  642. };
  643. var resource_filters = {
  644. "hosts": hosts
  645. };
  646. if (App.testMode) {
  647. this.getHostNameResolutionSuccess();
  648. } else {
  649. return App.ajax.send({
  650. name: 'preinstalled.checks',
  651. sender: this,
  652. data: {
  653. RequestInfo: RequestInfo,
  654. resource_filters: resource_filters
  655. },
  656. success: 'getHostNameResolutionSuccess',
  657. error: 'getHostNameResolutionError'
  658. });
  659. }
  660. },
  661. getHostNameResolutionSuccess: function(response) {
  662. if (!App.testMode) {
  663. this.set("requestId", response.Requests.id);
  664. }
  665. this.getHostCheckTasks();
  666. },
  667. getHostNameResolutionError: function() {
  668. this.getHostInfo();
  669. },
  670. /**
  671. * send ajax request to get all tasks
  672. * @method getHostCheckTasks
  673. */
  674. getHostCheckTasks: function () {
  675. var requestId = this.get("requestId");
  676. var self = this;
  677. this.set('startChecking', new Date().getTime());
  678. var checker = setInterval(function () {
  679. if (self.get('stopChecking') == true) {
  680. clearInterval(checker);
  681. self.getHostInfo();
  682. } else {
  683. App.ajax.send({
  684. name: 'preinstalled.checks.tasks',
  685. sender: self,
  686. data: {
  687. requestId: requestId
  688. },
  689. success: 'getHostCheckTasksSuccess',
  690. error: 'getHostCheckTasksError'
  691. });
  692. }
  693. }, 1000);
  694. },
  695. /**
  696. * add warnings to host warning popup if needed
  697. * @param data {Object} - json
  698. * @method getHostCheckTasksSuccess
  699. */
  700. getHostCheckTasksSuccess: function (data) {
  701. console.log('checking attempt...');
  702. if (!data) {
  703. console.warn("Error: jsonData is null");
  704. return;
  705. }
  706. this.set('stopChecking', true);
  707. data.tasks.forEach(function (task) {
  708. var cur = new Date().getTime();
  709. var name = Em.I18n.t('installer.step3.hostWarningsPopup.resolution.validation.error');
  710. var hostInfo = this.get("hostCheckWarnings").findProperty('name', name);
  711. if (task.Tasks.status == "FAILED" || (cur - this.get('startChecking') > 5000) || task.Tasks.status == "COMPLETED") {
  712. if (task.Tasks.status == "COMPLETED" && Em.get(task, 'Tasks.structured_out.host_resolution_check.failed_count') == 0) {
  713. return;
  714. }
  715. if (!hostInfo) {
  716. hostInfo = {
  717. name: name,
  718. hosts: [task.Tasks.host_name],
  719. onSingleHost: true
  720. };
  721. this.get("hostCheckWarnings").push(hostInfo);
  722. } else {
  723. hostInfo.hosts.push(task.Tasks.host_name);
  724. }
  725. } else {
  726. this.set('stopChecking', false);
  727. }
  728. }, this);
  729. },
  730. stopChecking: false,
  731. /**
  732. * startChecking {Number} - timestamp
  733. */
  734. startChecking: 0,
  735. /**
  736. * @method getHostCheckTasksError
  737. */
  738. getHostCheckTasksError: function() {
  739. console.warn("failed to cheek hostName resolution");
  740. this.set('stopChecking', true);
  741. },
  742. /**
  743. * Success-callback for hosts info request
  744. * @param {object} jsonData
  745. * @method getHostInfoSuccessCallback
  746. */
  747. getHostInfoSuccessCallback: function (jsonData) {
  748. var hosts = this.get('bootHosts'),
  749. self = this,
  750. repoWarnings = [],
  751. hostsContext = [],
  752. diskWarnings = [],
  753. hostsDiskContext = [],
  754. hostsDiskNames = [],
  755. hostsRepoNames = [];
  756. this.parseWarnings(jsonData);
  757. hosts.forEach(function (_host) {
  758. var host = (App.get('testMode')) ? jsonData.items[0] : jsonData.items.findProperty('Hosts.host_name', _host.name);
  759. if (App.get('skipBootstrap')) {
  760. self._setHostDataWithSkipBootstrap(_host);
  761. }
  762. else {
  763. if (host) {
  764. self._setHostDataFromLoadedHostInfo(_host, host);
  765. var host_name = Em.get(host, 'Hosts.host_name');
  766. var context = self.checkHostOSType(host.Hosts.os_type, host_name);
  767. if (context) {
  768. hostsContext.push(context);
  769. hostsRepoNames.push(host_name);
  770. }
  771. var diskContext = self.checkHostDiskSpace(host_name, host.Hosts.disk_info);
  772. if (diskContext) {
  773. hostsDiskContext.push(diskContext);
  774. hostsDiskNames.push(host_name);
  775. }
  776. }
  777. }
  778. });
  779. if (hostsContext.length > 0) { // warning exist
  780. repoWarnings.push({
  781. name: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.name'),
  782. hosts: hostsContext,
  783. hostsNames: hostsRepoNames,
  784. category: 'repositories',
  785. onSingleHost: false
  786. });
  787. }
  788. if (hostsDiskContext.length > 0) { // disk space warning exist
  789. diskWarnings.push({
  790. name: Em.I18n.t('installer.step3.hostWarningsPopup.disk.name'),
  791. hosts: hostsDiskContext,
  792. hostsNames: hostsDiskNames,
  793. category: 'disk',
  794. onSingleHost: false
  795. });
  796. }
  797. this.set('repoCategoryWarnings', repoWarnings);
  798. this.set('diskCategoryWarnings', diskWarnings);
  799. this.stopRegistration();
  800. },
  801. /**
  802. * Set metrics to host object
  803. * Used when <code>App.skipBootstrap</code> is true
  804. * @param {Ember.Object} host
  805. * @returns {object}
  806. * @private
  807. * @methos _setHostDataWithSkipBootstrap
  808. */
  809. _setHostDataWithSkipBootstrap: function(host) {
  810. host.set('cpu', 2);
  811. host.set('memory', ((parseInt(2000000))).toFixed(2));
  812. host.set('disk_info', [
  813. {"mountpoint": "/", "type": "ext4"},
  814. {"mountpoint": "/grid/0", "type": "ext4"},
  815. {"mountpoint": "/grid/1", "type": "ext4"},
  816. {"mountpoint": "/grid/2", "type": "ext4"}
  817. ]);
  818. return host;
  819. },
  820. /**
  821. * Set loaded metrics to host object
  822. * @param {object} host
  823. * @param {object} hostInfo
  824. * @returns {object}
  825. * @method _setHostDataFromLoadedHostInfo
  826. * @private
  827. */
  828. _setHostDataFromLoadedHostInfo: function(host, hostInfo) {
  829. host.set('cpu', Em.get(hostInfo, 'Hosts.cpu_count'));
  830. host.set('memory', ((parseInt(Em.get(hostInfo, 'Hosts.total_mem')))).toFixed(2));
  831. host.set('disk_info', Em.get(hostInfo, 'Hosts.disk_info').filter(function (h) {
  832. return h.mountpoint != "/boot"
  833. }));
  834. host.set('os_type', Em.get(hostInfo, 'Hosts.os_type'));
  835. host.set('os_arch', Em.get(hostInfo, 'Hosts.os_arch'));
  836. host.set('ip', Em.get(hostInfo, 'Hosts.ip'));
  837. return host;
  838. },
  839. /**
  840. * Error-callback for hosts info request
  841. * @method getHostInfoErrorCallback
  842. */
  843. getHostInfoErrorCallback: function () {
  844. console.log('INFO: Getting host information(cpu_count and total_mem) from the server failed');
  845. this.set('isWarningsLoaded', true);
  846. this.registerErrPopup(Em.I18n.t('installer.step3.hostInformation.popup.header'), Em.I18n.t('installer.step3.hostInformation.popup.body'));
  847. },
  848. /**
  849. * Enable or disable submit/retry buttons according to hosts boot statuses
  850. * @method stopRegistration
  851. */
  852. stopRegistration: function () {
  853. this.set('isSubmitDisabled', !this.get('bootHosts').someProperty('bootStatus', 'REGISTERED'));
  854. this.set('isRetryDisabled', !this.get('bootHosts').someProperty('bootStatus', 'FAILED'));
  855. },
  856. /**
  857. * Check if the customized os group contains the registered host os type. If not the repo on that host is invalid.
  858. * @param {string} osType
  859. * @param {string} hostName
  860. * @return {string} error-message or empty string
  861. * @method checkHostOSType
  862. */
  863. checkHostOSType: function (osType, hostName) {
  864. if (this.get('content.stacks')) {
  865. var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
  866. var selectedOS = [];
  867. var self = this;
  868. var isValid = false;
  869. if (selectedStack && selectedStack.operatingSystems) {
  870. selectedStack.get('operatingSystems').filterProperty('selected', true).forEach(function (os) {
  871. selectedOS.pushObject(os.osType);
  872. if (self.repoToAgentOsType(os.osType).indexOf(osType) >= 0) {
  873. isValid = true;
  874. }
  875. });
  876. }
  877. if (isValid) {
  878. return '';
  879. } else {
  880. console.log('WARNING: Getting host os type does NOT match the user selected os group in step1. ' +
  881. 'Host Name: ' + hostName + '. Host os type:' + osType + '. Selected group:' + selectedOS.uniq());
  882. return Em.I18n.t('installer.step3.hostWarningsPopup.repositories.context').format(hostName, osType, selectedOS.uniq());
  883. }
  884. } else {
  885. return '';
  886. }
  887. },
  888. /**
  889. * return the supported agent os types for a repo os type
  890. * @param {String} repoType
  891. * @return {Array} supported agent os type array
  892. * @method repoToAgentOsType
  893. */
  894. repoToAgentOsType : function (repoType) {
  895. switch (repoType) {
  896. case "redhat6":
  897. return ["redhat6", "centos6", "oraclelinux6", "rhel6"];
  898. case "redhat5":
  899. return ["redhat5", "centos5", "oraclelinux5", "rhel5"];
  900. case "suse11":
  901. return ["suse11", "sles11", "opensuse11"];
  902. case "debian12":
  903. return ["debian12", "ubuntu12"];
  904. default:
  905. return [];
  906. }
  907. },
  908. /**
  909. * Check if current host has enough free disk usage.
  910. * @param {string} hostName
  911. * @param {object} diskInfo
  912. * @return {string} error-message or empty string
  913. * @method checkHostDiskSpace
  914. */
  915. checkHostDiskSpace: function (hostName, diskInfo) {
  916. var minFreeRootSpace = App.minDiskSpace * 1024 * 1024; //in kilobyte
  917. var minFreeUsrLibSpace = App.minDiskSpaceUsrLib * 1024 * 1024; //in kilobyte
  918. var warningString = '';
  919. diskInfo.forEach(function (info) {
  920. switch (info.mountpoint) {
  921. case '/':
  922. warningString = info.available < minFreeRootSpace ?
  923. Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpace + 'GB', info.mountpoint) + ' ' + warningString :
  924. warningString;
  925. break;
  926. case '/usr':
  927. case '/usr/lib':
  928. warningString = info.available < minFreeUsrLibSpace ?
  929. Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpaceUsrLib + 'GB', info.mountpoint) + ' ' + warningString :
  930. warningString;
  931. break;
  932. default:
  933. break;
  934. }
  935. });
  936. if (warningString) {
  937. console.log('WARNING: Getting host free disk space. ' + 'Host Name: ' + hostName);
  938. return Em.I18n.t('installer.step3.hostWarningsPopup.disk.context1').format(hostName) + ' ' + warningString;
  939. } else {
  940. return '';
  941. }
  942. },
  943. /**
  944. * Submit-click handler
  945. * @return {App.ModalPopup|null}
  946. * @method submit
  947. */
  948. submit: function () {
  949. if (this.get('isHostHaveWarnings')) {
  950. var self = this;
  951. return App.showConfirmationPopup(
  952. function () {
  953. self.set('content.hosts', self.get('bootHosts'));
  954. App.router.send('next');
  955. },
  956. Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
  957. }
  958. else {
  959. this.set('content.hosts', this.get('bootHosts'));
  960. App.router.send('next');
  961. }
  962. return null;
  963. },
  964. /**
  965. * Show popup with host log
  966. * @param {object} event
  967. * @return {App.ModalPopup}
  968. */
  969. hostLogPopup: function (event) {
  970. var host = event.context;
  971. return App.ModalPopup.show({
  972. header: Em.I18n.t('installer.step3.hostLog.popup.header').format(host.get('name')),
  973. secondary: null,
  974. host: host,
  975. bodyClass: App.WizardStep3HostLogPopupBody
  976. });
  977. },
  978. /**
  979. * Check warnings from server and put it in parsing
  980. * @method rerunChecks
  981. */
  982. rerunChecks: function () {
  983. var self = this;
  984. var currentProgress = 0;
  985. var interval = setInterval(function () {
  986. currentProgress += 100000 / self.get('warningsTimeInterval');
  987. if (currentProgress < 100) {
  988. self.set('checksUpdateProgress', currentProgress);
  989. } else {
  990. clearInterval(interval);
  991. App.ajax.send({
  992. name: 'wizard.step3.rerun_checks',
  993. sender: self,
  994. success: 'rerunChecksSuccessCallback',
  995. error: 'rerunChecksErrorCallback'
  996. });
  997. }
  998. }, 1000);
  999. },
  1000. /**
  1001. * Success-callback for rerun request
  1002. * @param {object} data
  1003. * @method rerunChecksSuccessCallback
  1004. */
  1005. rerunChecksSuccessCallback: function (data) {
  1006. this.set('checksUpdateProgress', 100);
  1007. this.set('checksUpdateStatus', 'SUCCESS');
  1008. this.parseWarnings(data);
  1009. },
  1010. /**
  1011. * Error-callback for rerun request
  1012. * @method rerunChecksErrorCallback
  1013. */
  1014. rerunChecksErrorCallback: function () {
  1015. this.set('checksUpdateProgress', 100);
  1016. this.set('checksUpdateStatus', 'FAILED');
  1017. console.log('INFO: Getting host information(last_agent_env) from the server failed');
  1018. },
  1019. /**
  1020. * Filter data for warnings parse
  1021. * is data from host in bootStrap
  1022. * @param {object} data
  1023. * @return {Object}
  1024. * @method filterBootHosts
  1025. */
  1026. filterBootHosts: function (data) {
  1027. var bootHostNames = {};
  1028. this.get('bootHosts').forEach(function (bootHost) {
  1029. bootHostNames[bootHost.get('name')] = true;
  1030. });
  1031. var filteredData = {
  1032. href: data.href,
  1033. items: []
  1034. };
  1035. data.items.forEach(function (host) {
  1036. if (bootHostNames[host.Hosts.host_name]) {
  1037. filteredData.items.push(host);
  1038. }
  1039. });
  1040. return filteredData;
  1041. },
  1042. /**
  1043. * Parse warnings data for each host and total
  1044. * @param {object} data
  1045. * @method parseWarnings
  1046. */
  1047. parseWarnings: function (data) {
  1048. data = App.testMode ? data : this.filterBootHosts(data);
  1049. var warnings = [];
  1050. var warning;
  1051. var hosts = [];
  1052. var warningCategories = {
  1053. fileFoldersWarnings: {},
  1054. packagesWarnings: {},
  1055. processesWarnings: {},
  1056. servicesWarnings: {},
  1057. usersWarnings: {},
  1058. alternativeWarnings: {}
  1059. };
  1060. data.items.sortPropertyLight('Hosts.host_name').forEach(function (_host) {
  1061. var host = {
  1062. name: _host.Hosts.host_name,
  1063. warnings: []
  1064. };
  1065. if (!_host.Hosts.last_agent_env) {
  1066. // in some unusual circumstances when last_agent_env is not available from the _host,
  1067. // skip the _host and proceed to process the rest of the hosts.
  1068. console.log("last_agent_env is missing for " + _host.Hosts.host_name + ". Skipping _host check.");
  1069. return;
  1070. }
  1071. //parse all directories and files warnings for host
  1072. //todo: to be removed after check in new API
  1073. var stackFoldersAndFiles = _host.Hosts.last_agent_env.stackFoldersAndFiles || [];
  1074. stackFoldersAndFiles.forEach(function (path) {
  1075. warning = warningCategories.fileFoldersWarnings[path.name];
  1076. if (warning) {
  1077. warning.hosts.push(_host.Hosts.host_name);
  1078. warning.onSingleHost = false;
  1079. } else {
  1080. warningCategories.fileFoldersWarnings[path.name] = warning = {
  1081. name: path.name,
  1082. hosts: [_host.Hosts.host_name],
  1083. category: 'fileFolders',
  1084. onSingleHost: true
  1085. };
  1086. }
  1087. host.warnings.push(warning);
  1088. }, this);
  1089. //parse all package warnings for host
  1090. if (_host.Hosts.last_agent_env.installedPackages) {
  1091. _host.Hosts.last_agent_env.installedPackages.forEach(function (_package) {
  1092. warning = warningCategories.packagesWarnings[_package.name];
  1093. if (warning) {
  1094. warning.hosts.push(_host.Hosts.host_name);
  1095. warning.version = _package.version;
  1096. warning.onSingleHost = false;
  1097. } else {
  1098. warningCategories.packagesWarnings[_package.name] = warning = {
  1099. name: _package.name,
  1100. version: _package.version,
  1101. hosts: [_host.Hosts.host_name],
  1102. category: 'packages',
  1103. onSingleHost: true
  1104. };
  1105. }
  1106. host.warnings.push(warning);
  1107. }, this);
  1108. }
  1109. //parse all process warnings for host
  1110. //todo: to be removed after check in new API
  1111. var javaProcs = _host.Hosts.last_agent_env.hostHealth ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs : _host.Hosts.last_agent_env.javaProcs;
  1112. if (javaProcs) {
  1113. javaProcs.forEach(function (process) {
  1114. warning = warningCategories.processesWarnings[process.pid];
  1115. if (warning) {
  1116. warning.hosts.push(_host.Hosts.host_name);
  1117. warning.onSingleHost = false;
  1118. } else {
  1119. warningCategories.processesWarnings[process.pid] = warning = {
  1120. name: (process.command.substr(0, 35) + '...'),
  1121. hosts: [_host.Hosts.host_name],
  1122. category: 'processes',
  1123. user: process.user,
  1124. pid: process.pid,
  1125. command: '<table><tr><td style="word-break: break-all;">' +
  1126. ((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
  1127. '<p style="text-align: center">................</p>' +
  1128. '...' + process.command.substr(-230)) + '</td></tr></table>',
  1129. onSingleHost: true
  1130. };
  1131. }
  1132. host.warnings.push(warning);
  1133. }, this);
  1134. }
  1135. //parse all service warnings for host
  1136. //todo: to be removed after check in new API
  1137. if (_host.Hosts.last_agent_env.hostHealth && _host.Hosts.last_agent_env.hostHealth.liveServices) {
  1138. _host.Hosts.last_agent_env.hostHealth.liveServices.forEach(function (service) {
  1139. if (service.status === 'Unhealthy') {
  1140. warning = warningCategories.servicesWarnings[service.name];
  1141. if (warning) {
  1142. warning.hosts.push(_host.Hosts.host_name);
  1143. warning.onSingleHost = false;
  1144. } else {
  1145. warningCategories.servicesWarnings[service.name] = warning = {
  1146. name: service.name,
  1147. hosts: [_host.Hosts.host_name],
  1148. category: 'services',
  1149. onSingleHost: true
  1150. };
  1151. }
  1152. host.warnings.push(warning);
  1153. }
  1154. }, this);
  1155. }
  1156. //parse all user warnings for host
  1157. //todo: to be removed after check in new API
  1158. if (_host.Hosts.last_agent_env.existingUsers) {
  1159. _host.Hosts.last_agent_env.existingUsers.forEach(function (user) {
  1160. warning = warningCategories.usersWarnings[user.userName];
  1161. if (warning) {
  1162. warning.hosts.push(_host.Hosts.host_name);
  1163. warning.onSingleHost = false;
  1164. } else {
  1165. warningCategories.usersWarnings[user.userName] = warning = {
  1166. name: user.userName,
  1167. hosts: [_host.Hosts.host_name],
  1168. category: 'users',
  1169. onSingleHost: true
  1170. };
  1171. }
  1172. host.warnings.push(warning);
  1173. }, this);
  1174. }
  1175. //parse misc warnings for host
  1176. var umask = _host.Hosts.last_agent_env.umask;
  1177. if (umask && umask !== 18) {
  1178. warning = warnings.filterProperty('category', 'misc').findProperty('name', umask);
  1179. if (warning) {
  1180. warning.hosts.push(_host.Hosts.host_name);
  1181. warning.onSingleHost = false;
  1182. } else {
  1183. warning = {
  1184. name: umask,
  1185. hosts: [_host.Hosts.host_name],
  1186. category: 'misc',
  1187. onSingleHost: true
  1188. };
  1189. warnings.push(warning);
  1190. }
  1191. host.warnings.push(warning);
  1192. }
  1193. var firewallRunning = _host.Hosts.last_agent_env.iptablesIsRunning;
  1194. if (firewallRunning !== null && firewallRunning) {
  1195. var name = Em.I18n.t('installer.step3.hostWarningsPopup.firewall.name');
  1196. warning = warnings.filterProperty('category', 'firewall').findProperty('name', name);
  1197. if (warning) {
  1198. warning.hosts.push(_host.Hosts.host_name);
  1199. warning.onSingleHost = false;
  1200. } else {
  1201. warning = {
  1202. name: name,
  1203. hosts: [_host.Hosts.host_name],
  1204. category: 'firewall',
  1205. onSingleHost: true
  1206. };
  1207. warnings.push(warning);
  1208. }
  1209. host.warnings.push(warning);
  1210. }
  1211. if (_host.Hosts.last_agent_env.alternatives) {
  1212. _host.Hosts.last_agent_env.alternatives.forEach(function (alternative) {
  1213. warning = warningCategories.alternativeWarnings[alternative.name];
  1214. if (warning) {
  1215. warning.hosts.push(_host.Hosts.host_name);
  1216. warning.onSingleHost = false;
  1217. } else {
  1218. warningCategories.alternativeWarnings[alternative.name] = warning = {
  1219. name: alternative.name,
  1220. target: alternative.target,
  1221. hosts: [_host.Hosts.host_name],
  1222. category: 'alternatives',
  1223. onSingleHost: true
  1224. };
  1225. }
  1226. host.warnings.push(warning);
  1227. }, this);
  1228. }
  1229. if (_host.Hosts.last_agent_env.reverseLookup === false) {
  1230. var name = Em.I18n.t('installer.step3.hostWarningsPopup.reverseLookup.name');
  1231. warning = warnings.filterProperty('category', 'reverseLookup').findProperty('name', name);
  1232. if (warning) {
  1233. warning.hosts.push(_host.Hosts.host_name);
  1234. warning.onSingleHost = false;
  1235. } else {
  1236. warning = {
  1237. name: name,
  1238. hosts: [_host.Hosts.host_name],
  1239. category: 'reverseLookup',
  1240. onSingleHost: true
  1241. };
  1242. warnings.push(warning);
  1243. }
  1244. host.warnings.push(warning);
  1245. }
  1246. hosts.push(host);
  1247. }, this);
  1248. for (var categoryId in warningCategories) {
  1249. var category = warningCategories[categoryId]
  1250. for (var warningId in category) {
  1251. warnings.push(category[warningId]);
  1252. }
  1253. }
  1254. warnings.forEach(function (warn) {
  1255. if (warn.hosts.length < 11) {
  1256. warn.hostsList = warn.hosts.join('<br>')
  1257. } else {
  1258. warn.hostsList = warn.hosts.slice(0, 10).join('<br>') + '<br> ' + Em.I18n.t('installer.step3.hostWarningsPopup.moreHosts').format(warn.hosts.length - 10);
  1259. }
  1260. });
  1261. hosts.unshift({
  1262. name: 'All Hosts',
  1263. warnings: warnings
  1264. });
  1265. this.set('warnings', warnings);
  1266. this.set('warningsByHost', hosts);
  1267. this.set('isWarningsLoaded', true);
  1268. },
  1269. /**
  1270. * Open popup that contain hosts' warnings
  1271. * @return {App.ModalPopup}
  1272. * @method hostWarningsPopup
  1273. */
  1274. hostWarningsPopup: function () {
  1275. var self = this;
  1276. return App.ModalPopup.show({
  1277. header: Em.I18n.t('installer.step3.warnings.popup.header'),
  1278. secondary: Em.I18n.t('installer.step3.hostWarningsPopup.rerunChecks'),
  1279. primary: Em.I18n.t('common.close'),
  1280. onPrimary: function () {
  1281. self.set('checksUpdateStatus', null);
  1282. this.hide();
  1283. },
  1284. onClose: function () {
  1285. self.set('checksUpdateStatus', null);
  1286. this.hide();
  1287. },
  1288. onSecondary: function () {
  1289. self.rerunChecks();
  1290. },
  1291. didInsertElement: function () {
  1292. this.fitHeight();
  1293. },
  1294. footerClass: App.WizardStep3HostWarningPopupFooter,
  1295. bodyClass: App.WizardStep3HostWarningPopupBody
  1296. });
  1297. },
  1298. /**
  1299. * Show popup with registered hosts
  1300. * @return {App.ModalPopup}
  1301. * @method registeredHostsPopup
  1302. */
  1303. registeredHostsPopup: function () {
  1304. var self = this;
  1305. return App.ModalPopup.show({
  1306. header: Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('registeredHosts').length),
  1307. secondary: null,
  1308. bodyClass: Em.View.extend({
  1309. templateName: require('templates/wizard/step3/step3_registered_hosts_popup'),
  1310. message: Em.I18n.t('installer.step3.registeredHostsPopup'),
  1311. registeredHosts: self.get('registeredHosts')
  1312. })
  1313. })
  1314. }
  1315. });