step3_controller.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  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. App.WizardStep3Controller = Em.Controller.extend({
  21. name: 'wizardStep3Controller',
  22. hosts: [],
  23. content: [],
  24. bootHosts: [],
  25. registeredHosts: [],
  26. registrationStartedAt: null,
  27. registrationTimeoutSecs: function(){
  28. if(this.get('content.installOptions.manualInstall')){
  29. return 15;
  30. }
  31. return 120;
  32. }.property('content.installOptions.manualInstall'),
  33. stopBootstrap: false,
  34. isSubmitDisabled: true,
  35. categoryObject: Em.Object.extend({
  36. hostsCount: function () {
  37. var category = this;
  38. var hosts = this.get('controller.hosts').filter(function(_host) {
  39. if (_host.get('bootStatus') == category.get('hostsBootStatus')) {
  40. return true;
  41. } else {
  42. return (_host.get('bootStatus') == 'DONE' && category.get('hostsBootStatus') == 'REGISTERING');
  43. }
  44. }, this);
  45. return hosts.get('length');
  46. }.property('controller.hosts.@each.bootStatus'), // 'hosts.@each.bootStatus'
  47. label: function () {
  48. return "%@ (%@)".fmt(this.get('value'), this.get('hostsCount'));
  49. }.property('value', 'hostsCount')
  50. }),
  51. getCategory: function(field, value){
  52. return this.get('categories').find(function(item){
  53. return item.get(field) == value;
  54. });
  55. },
  56. categories: function () {
  57. var self = this;
  58. self.categoryObject.reopen({
  59. controller: self,
  60. isActive: function(){
  61. return this.get('controller.category') == this;
  62. }.property('controller.category'),
  63. itemClass: function(){
  64. return this.get('isActive') ? 'active' : '';
  65. }.property('isActive')
  66. });
  67. var categories = [
  68. self.categoryObject.create({value: Em.I18n.t('common.all'), hostsCount: function () {
  69. return this.get('controller.hosts.length');
  70. }.property('controller.hosts.length') }),
  71. self.categoryObject.create({value: Em.I18n.t('installer.step3.hosts.status.installing'), hostsBootStatus: 'RUNNING'}),
  72. self.categoryObject.create({value: Em.I18n.t('installer.step3.hosts.status.registering'), hostsBootStatus: 'REGISTERING'}),
  73. self.categoryObject.create({value: Em.I18n.t('common.success'), hostsBootStatus: 'REGISTERED' }),
  74. self.categoryObject.create({value: Em.I18n.t('common.fail'), hostsBootStatus: 'FAILED', last: true })
  75. ];
  76. this.set('category', categories.get('firstObject'));
  77. return categories;
  78. }.property(),
  79. category: false,
  80. allChecked: false,
  81. onAllChecked: function () {
  82. var hosts = this.get('visibleHosts');
  83. hosts.setEach('isChecked', this.get('allChecked'));
  84. }.observes('allChecked'),
  85. noHostsSelected: function () {
  86. return !(this.hosts.someProperty('isChecked', true));
  87. }.property('hosts.@each.isChecked'),
  88. isRetryDisabled: true,
  89. isLoaded: false,
  90. navigateStep: function () {
  91. if(this.get('isLoaded')){
  92. if (this.get('content.installOptions.manualInstall') !== true) {
  93. if (!this.get('wizardController').getDBProperty('bootStatus')) {
  94. this.startBootstrap();
  95. }
  96. } else {
  97. this.set('bootHosts', this.get('hosts'));
  98. if (App.testMode) {
  99. this.getHostInfo();
  100. this.get('bootHosts').setEach('bootStatus', 'REGISTERED');
  101. this.get('bootHosts').setEach('cpu', '2');
  102. this.get('bootHosts').setEach('memory', '2000000');
  103. this.set('isSubmitDisabled', false);
  104. } else {
  105. this.set('registrationStartedAt', null);
  106. this.get('bootHosts').setEach('bootStatus', 'DONE');
  107. this.startRegistration();
  108. }
  109. }
  110. }
  111. }.observes('isLoaded'),
  112. clearStep: function () {
  113. this.set('stopBootstrap', false);
  114. this.set('hosts', []);
  115. this.get('bootHosts').clear();
  116. this.get('wizardController').setDBProperty('bootStatus', false);
  117. this.set('isSubmitDisabled', true);
  118. this.set('isRetryDisabled', true);
  119. },
  120. loadStep: function () {
  121. console.log("TRACE: Loading step3: Confirm Hosts");
  122. this.set('registrationStartedAt', null);
  123. this.set('isLoaded', false);
  124. this.clearStep();
  125. this.loadHosts();
  126. // hosts.setEach('bootStatus', 'RUNNING');
  127. },
  128. /* Loads the hostinfo from localStorage on the insertion of view. It's being called from view */
  129. loadHosts: function () {
  130. var hostsInfo = this.get('content.hosts');
  131. var hosts = [];
  132. for (var index in hostsInfo) {
  133. var hostInfo = App.HostInfo.create({
  134. name: hostsInfo[index].name,
  135. bootStatus: hostsInfo[index].bootStatus,
  136. isChecked: false
  137. });
  138. console.log('pushing ' + hostInfo.name);
  139. hosts.pushObject(hostInfo);
  140. }
  141. if(hosts.length > 100) {
  142. lazyloading.run({
  143. destination: this.get('hosts'),
  144. source: hosts,
  145. context: this,
  146. initSize: 20,
  147. chunkSize: 100,
  148. delay: 300
  149. });
  150. } else {
  151. this.set('hosts', hosts);
  152. this.set('isLoaded', true);
  153. }
  154. },
  155. /**
  156. * Parses and updates the content based on bootstrap API response.
  157. * Returns true if polling should continue (some hosts are in "RUNNING" state); false otherwise
  158. */
  159. parseHostInfo: function (hostsStatusFromServer) {
  160. hostsStatusFromServer.forEach(function (_hostStatus) {
  161. var host = this.get('bootHosts').findProperty('name', _hostStatus.hostName);
  162. // check if hostname extracted from REST API data matches any hostname in content
  163. // also, make sure that bootStatus modified by isHostsRegistered call does not get overwritten
  164. // since these calls are being made in parallel
  165. if (host && !['REGISTERED', 'REGISTERING'].contains(host.get('bootStatus'))) {
  166. host.set('bootStatus', _hostStatus.status);
  167. host.set('bootLog', _hostStatus.log);
  168. }
  169. }, this);
  170. // if the data rendered by REST API has hosts in "RUNNING" state, polling will continue
  171. return this.get('bootHosts').length != 0 && this.get('bootHosts').someProperty('bootStatus', 'RUNNING');
  172. },
  173. /* Returns the current set of visible hosts on view (All, Succeeded, Failed) */
  174. visibleHosts: function () {
  175. if (this.get('category.hostsBootStatus')) {
  176. return this.hosts.filterProperty('bootStatus', this.get('category.hostsBootStatus'));
  177. } else { // if (this.get('category') === 'All Hosts')
  178. return this.hosts;
  179. }
  180. }.property('category', 'hosts.@each.bootStatus'),
  181. removeHosts: function (hosts) {
  182. var self = this;
  183. App.showConfirmationPopup(function() {
  184. App.router.send('removeHosts', hosts);
  185. self.hosts.removeObjects(hosts);
  186. if (!self.hosts.length) {
  187. self.set('isSubmitDisabled', true);
  188. }
  189. },Em.I18n.t('installer.step3.hosts.remove.popup.body'));
  190. },
  191. /* Removes a single element on the trash icon click. Called from View */
  192. removeHost: function (hostInfo) {
  193. this.removeHosts([hostInfo]);
  194. },
  195. removeSelectedHosts: function () {
  196. if (!this.get('noHostsSelected')) {
  197. var selectedHosts = this.get('visibleHosts').filterProperty('isChecked', true);
  198. selectedHosts.forEach(function (_hostInfo) {
  199. console.log('Removing: ' + _hostInfo.name);
  200. });
  201. this.removeHosts(selectedHosts);
  202. }
  203. },
  204. retryHost: function (hostInfo) {
  205. this.retryHosts([hostInfo]);
  206. },
  207. retryHosts: function (hosts) {
  208. var bootStrapData = JSON.stringify({'verbose': true, 'sshKey': this.get('content.installOptions.sshKey'), 'hosts': hosts.mapProperty('name'), 'user': this.get('content.installOptions.sshUser')});
  209. this.numPolls = 0;
  210. if (this.get('content.installOptions.manualInstall') !== true) {
  211. var requestId = App.router.get('installerController').launchBootstrap(bootStrapData);
  212. this.set('content.installOptions.bootRequestId', requestId);
  213. this.set('registrationStartedAt', null);
  214. this.doBootstrap();
  215. } else {
  216. this.set('registrationStartedAt', null);
  217. this.get('bootHosts').setEach('bootStatus', 'DONE');
  218. this.startRegistration();
  219. }
  220. },
  221. retrySelectedHosts: function () {
  222. //to display all hosts
  223. this.set('category', 'All');
  224. if (!this.get('isRetryDisabled')) {
  225. this.set('isRetryDisabled', true);
  226. var selectedHosts = this.get('bootHosts').filterProperty('bootStatus', 'FAILED');
  227. selectedHosts.forEach(function (_host) {
  228. _host.set('bootStatus', 'RUNNING');
  229. _host.set('bootLog', 'Retrying ...');
  230. }, this);
  231. this.retryHosts(selectedHosts);
  232. }
  233. },
  234. numPolls: 0,
  235. startBootstrap: function () {
  236. //this.set('isSubmitDisabled', true); //TODO: uncomment after actual hookup
  237. this.numPolls = 0;
  238. this.set('registrationStartedAt', null);
  239. this.set('bootHosts', this.get('hosts'));
  240. this.get('bootHosts').setEach('bootStatus', 'PENDING');
  241. this.doBootstrap();
  242. },
  243. isInstallInProgress: function(){
  244. var bootStatuses = this.get('bootHosts').getEach('bootStatus');
  245. if(bootStatuses.length &&
  246. (bootStatuses.contains('REGISTERING') ||
  247. bootStatuses.contains('DONE') ||
  248. bootStatuses.contains('RUNNING') ||
  249. bootStatuses.contains('PENDING'))){
  250. return true;
  251. }
  252. return false;
  253. }.property('bootHosts.@each.bootStatus'),
  254. disablePreviousSteps: function(){
  255. if(this.get('isInstallInProgress')){
  256. App.router.get('installerController').setLowerStepsDisable(3);
  257. this.set('isSubmitDisabled', true);
  258. } else {
  259. App.router.get('installerController.isStepDisabled').filter(function(step){
  260. if(step.step >= 0 && step.step <= 2) return true;
  261. }).setEach('value', false);
  262. }
  263. }.observes('isInstallInProgress'),
  264. doBootstrap: function () {
  265. if (this.get('stopBootstrap')) {
  266. return;
  267. }
  268. this.numPolls++;
  269. App.ajax.send({
  270. name: 'wizard.step3.bootstrap',
  271. sender: this,
  272. data: {
  273. bootRequestId: this.get('content.installOptions.bootRequestId'),
  274. numPolls: this.numPolls
  275. },
  276. success: 'doBootstrapSuccessCallback'
  277. }).
  278. retry({
  279. times: App.maxRetries,
  280. timeout: App.timeout
  281. }).
  282. then(
  283. null,
  284. function () {
  285. App.showReloadPopup();
  286. console.log('Bootstrap failed');
  287. }
  288. );
  289. },
  290. doBootstrapSuccessCallback: function (data) {
  291. var self = this;
  292. var pollingInterval = 3000;
  293. if (data.hostsStatus === undefined) {
  294. console.log('Invalid response, setting timeout');
  295. window.setTimeout(function () {
  296. self.doBootstrap()
  297. }, pollingInterval);
  298. } else {
  299. // in case of bootstrapping just one host, the server returns an object rather than an array, so
  300. // force into an array
  301. if (!(data.hostsStatus instanceof Array)) {
  302. data.hostsStatus = [ data.hostsStatus ];
  303. }
  304. console.log("TRACE: In success function for the GET bootstrap call");
  305. var keepPolling = this.parseHostInfo(data.hostsStatus);
  306. // Single host : if the only hostname is invalid (data.status == 'ERROR')
  307. // Multiple hosts : if one or more hostnames are invalid
  308. // following check will mark the bootStatus as 'FAILED' for the invalid hostname
  309. if (data.status == 'ERROR' || data.hostsStatus.length != this.get('bootHosts').length) {
  310. var hosts = this.get('bootHosts');
  311. for (var i = 0; i < hosts.length; i++) {
  312. var isValidHost = data.hostsStatus.someProperty('hostName', hosts[i].get('name'));
  313. if(hosts[i].get('bootStatus') !== 'REGISTERED'){
  314. if (!isValidHost) {
  315. hosts[i].set('bootStatus', 'FAILED');
  316. hosts[i].set('bootLog', Em.I18n.t('installer.step3.hosts.bootLog.failed'));
  317. }
  318. }
  319. }
  320. }
  321. if (data.hostsStatus.someProperty('status', 'DONE') || data.hostsStatus.someProperty('status', 'FAILED')) {
  322. // kicking off registration polls after at least one host has succeeded
  323. this.startRegistration();
  324. }
  325. if (keepPolling) {
  326. window.setTimeout(function () {
  327. self.doBootstrap()
  328. }, pollingInterval);
  329. }
  330. }
  331. },
  332. startRegistration: function () {
  333. if (this.get('registrationStartedAt') == null) {
  334. this.set('registrationStartedAt', new Date().getTime());
  335. console.log('registration started at ' + this.get('registrationStartedAt'));
  336. this.isHostsRegistered();
  337. }
  338. },
  339. isHostsRegistered: function () {
  340. if (this.get('stopBootstrap')) {
  341. return;
  342. }
  343. App.ajax.send({
  344. name: 'wizard.step3.is_hosts_registered',
  345. sender: this,
  346. success: 'isHostsRegisteredSuccessCallback'
  347. }).
  348. retry({
  349. times: App.maxRetries,
  350. timeout: App.timeout
  351. }).
  352. then(
  353. null,
  354. function () {
  355. App.showReloadPopup();
  356. console.log('Error: Getting registered host information from the server');
  357. }
  358. );
  359. },
  360. isHostsRegisteredSuccessCallback: function (data) {
  361. console.log('registration attempt...');
  362. var hosts = this.get('bootHosts');
  363. var jsonData = data;
  364. if (!jsonData) {
  365. console.warn("Error: jsonData is null");
  366. return;
  367. }
  368. // keep polling until all hosts have registered/failed, or registrationTimeout seconds after the last host finished bootstrapping
  369. var stopPolling = true;
  370. hosts.forEach(function (_host, index) {
  371. // Change name of first host for test mode.
  372. if (App.testMode) {
  373. if (index == 0) {
  374. _host.set('name', 'localhost.localdomain');
  375. }
  376. }
  377. // actions to take depending on the host's current bootStatus
  378. // RUNNING - bootstrap is running; leave it alone
  379. // DONE - bootstrap is done; transition to REGISTERING
  380. // REGISTERING - bootstrap is done but has not registered; transition to REGISTERED if host found in polling API result
  381. // REGISTERED - bootstrap and registration is done; leave it alone
  382. // FAILED - either bootstrap or registration failed; leave it alone
  383. switch (_host.get('bootStatus')) {
  384. case 'DONE':
  385. _host.set('bootStatus', 'REGISTERING');
  386. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
  387. // update registration timestamp so that the timeout is computed from the last host that finished bootstrapping
  388. this.set('registrationStartedAt', new Date().getTime());
  389. stopPolling = false;
  390. break;
  391. case 'REGISTERING':
  392. if (jsonData.items.someProperty('Hosts.host_name', _host.name)) {
  393. console.log(_host.name + ' has been registered');
  394. _host.set('bootStatus', 'REGISTERED');
  395. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
  396. } else {
  397. console.log(_host.name + ' is registering...');
  398. stopPolling = false;
  399. }
  400. break;
  401. case 'RUNNING':
  402. stopPolling = false;
  403. break;
  404. case 'REGISTERED':
  405. case 'FAILED':
  406. default:
  407. break;
  408. }
  409. }, this);
  410. if (stopPolling) {
  411. this.getHostInfo();
  412. } else if (hosts.someProperty('bootStatus', 'RUNNING') || new Date().getTime() - this.get('registrationStartedAt') < this.get('registrationTimeoutSecs') * 1000) {
  413. // we want to keep polling for registration status if any of the hosts are still bootstrapping (so we check for RUNNING).
  414. var self = this;
  415. window.setTimeout(function () {
  416. self.isHostsRegistered();
  417. }, 3000);
  418. } else {
  419. // registration timed out. mark all REGISTERING hosts to FAILED
  420. console.log('registration timed out');
  421. hosts.filterProperty('bootStatus', 'REGISTERING').forEach(function (_host) {
  422. _host.set('bootStatus', 'FAILED');
  423. _host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.failed'));
  424. });
  425. this.getHostInfo();
  426. }
  427. },
  428. hasMoreRegisteredHosts: false,
  429. getAllRegisteredHosts: function() {
  430. App.ajax.send({
  431. name: 'wizard.step3.is_hosts_registered',
  432. sender: this,
  433. success: 'getAllRegisteredHostsCallback'
  434. });
  435. }.observes('bootHosts'),
  436. hostsInCluster: function() {
  437. return App.Host.find().getEach('hostName');
  438. }.property().volatile(),
  439. getAllRegisteredHostsCallback: function(hosts) {
  440. var registeredHosts = [];
  441. var hostsInCluster = this.get('hostsInCluster');
  442. var addedHosts = this.get('bootHosts').getEach('name');
  443. hosts.items.forEach(function(host){
  444. if (!hostsInCluster.contains(host.Hosts.host_name) && !addedHosts.contains(host.Hosts.host_name)) {
  445. registeredHosts.push(host.Hosts.host_name);
  446. }
  447. });
  448. if(registeredHosts.length) {
  449. this.set('hasMoreRegisteredHosts',true);
  450. this.set('registeredHosts',registeredHosts);
  451. } else {
  452. this.set('hasMoreRegisteredHosts',false);
  453. this.set('registeredHosts','');
  454. }
  455. },
  456. allHostsComplete: function() {
  457. var result = true;
  458. this.get('bootHosts').forEach(function(host) {
  459. var status = host.get('bootStatus');
  460. if (status != 'REGISTERED' && status != 'FAILED') {
  461. result = false;
  462. }
  463. });
  464. return result;
  465. }.property('bootHosts.@each.bootStatus'),
  466. registerErrPopup: function (header, message) {
  467. App.ModalPopup.show({
  468. header: header,
  469. secondary: false,
  470. onPrimary: function () {
  471. this.hide();
  472. },
  473. bodyClass: Ember.View.extend({
  474. template: Ember.Handlebars.compile(['<p>{{view.message}}</p>'].join('\n')),
  475. message: message
  476. })
  477. });
  478. },
  479. /**
  480. * Get disk info and cpu count of booted hosts from server
  481. */
  482. getHostInfo: function () {
  483. App.ajax.send({
  484. name: 'wizard.step3.host_info',
  485. sender: this,
  486. success: 'getHostInfoSuccessCallback',
  487. error: 'getHostInfoErrorCallback'
  488. });
  489. },
  490. getHostInfoSuccessCallback: function (jsonData) {
  491. var hosts = this.get('bootHosts');
  492. var self = this;
  493. this.parseWarnings(jsonData);
  494. var repoWarnings = [];
  495. var hostsContext = [];
  496. hosts.forEach(function (_host) {
  497. var host = (App.testMode) ? jsonData.items[0] : jsonData.items.findProperty('Hosts.host_name', _host.name);
  498. if (App.skipBootstrap) {
  499. _host.cpu = 2;
  500. _host.memory = ((parseInt(2000000))).toFixed(2);
  501. _host.disk_info = [{"mountpoint": "/", "type":"ext4"},{"mountpoint": "/grid/0", "type":"ext4"}, {"mountpoint": "/grid/1", "type":"ext4"}, {"mountpoint": "/grid/2", "type":"ext4"}];
  502. } else if (host) {
  503. _host.cpu = host.Hosts.cpu_count;
  504. _host.memory = ((parseInt(host.Hosts.total_mem))).toFixed(2);
  505. _host.disk_info = host.Hosts.disk_info;
  506. _host.os_type = host.Hosts.os_type;
  507. var context = self.checkHostOSType(host.Hosts.os_type, host.Hosts.host_name);
  508. if(context) {
  509. hostsContext.push(context);
  510. }
  511. console.log("The value of memory is: " + _host.memory);
  512. }
  513. });
  514. if (hostsContext.length > 0) { // warning exist
  515. var repoWarning = {
  516. name: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.name'),
  517. hosts: hostsContext,
  518. category: 'repositories',
  519. onSingleHost: false
  520. };
  521. repoWarnings.push(repoWarning);
  522. }
  523. this.set('repoCategoryWarnings', repoWarnings);
  524. this.set('bootHosts', hosts);
  525. console.log("The value of hosts: " + JSON.stringify(hosts));
  526. this.stopRegistration();
  527. },
  528. getHostInfoErrorCallback: function () {
  529. console.log('INFO: Getting host information(cpu_count and total_mem) from the server failed');
  530. this.registerErrPopup(Em.I18n.t('installer.step3.hostInformation.popup.header'), Em.I18n.t('installer.step3.hostInformation.popup.body'));
  531. },
  532. stopRegistration: function () {
  533. this.set('isSubmitDisabled', !this.get('bootHosts').someProperty('bootStatus', 'REGISTERED'));
  534. this.set('isRetryDisabled', !this.get('bootHosts').someProperty('bootStatus', 'FAILED'));
  535. },
  536. /**
  537. * Check if the customized os group contains the registered host os type. If not the repo on that host is invalid.
  538. */
  539. checkHostOSType: function (osType, hostName) {
  540. if(this.get('content.stacks')){
  541. var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
  542. var selectedOS = [];
  543. var isValid = false;
  544. if (selectedStack && selectedStack.operatingSystems) {
  545. selectedStack.get('operatingSystems').filterProperty('selected', true).forEach( function(os) {
  546. selectedOS.pushObject(os.osType);
  547. if ( os.osType == osType) {
  548. isValid = true;
  549. }
  550. });
  551. }
  552. if (!isValid) {
  553. console.log('WARNING: Getting host os type does NOT match the user selected os group in step1. ' +
  554. 'Host Name: '+ hostName + '. Host os type:' + osType + '. Selected group:' + selectedOS);
  555. return Em.I18n.t('installer.step3.hostWarningsPopup.repositories.context').format(hostName, osType, selectedOS);
  556. } else {
  557. return null;
  558. }
  559. }else{
  560. return null;
  561. }
  562. },
  563. selectCategory: function(event, context){
  564. this.set('category', event.context);
  565. },
  566. submit: function () {
  567. if (!this.get('isSubmitDisabled')) {
  568. if(this.get('isHostHaveWarnings')) {
  569. var self = this;
  570. App.showConfirmationPopup(
  571. function(){
  572. self.set('content.hosts', self.get('bootHosts'));
  573. App.router.send('next');
  574. },
  575. Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
  576. }
  577. else {
  578. this.set('content.hosts', this.get('bootHosts'));
  579. App.router.send('next');
  580. }
  581. }
  582. },
  583. hostLogPopup: function (event, context) {
  584. var host = event.context;
  585. App.ModalPopup.show({
  586. header: Em.I18n.t('installer.step3.hostLog.popup.header').format(host.get('name')),
  587. secondary: null,
  588. onPrimary: function () {
  589. this.hide();
  590. },
  591. bodyClass: Ember.View.extend({
  592. templateName: require('templates/wizard/step3_host_log_popup'),
  593. host: host,
  594. didInsertElement: function () {
  595. var self = this;
  596. var button = $(this.get('element')).find('.textTrigger');
  597. button.click(function () {
  598. if (self.get('isTextArea')) {
  599. $(this).text(Em.I18n.t('installer.step3.hostLogPopup.highlight'));
  600. } else {
  601. $(this).text(Em.I18n.t('installer.step3.hostLogPopup.copy'));
  602. }
  603. self.set('isTextArea', !self.get('isTextArea'));
  604. });
  605. $(this.get('element')).find('.content-area').mouseenter(
  606. function () {
  607. var element = $(this);
  608. element.css('border', '1px solid #dcdcdc');
  609. button.css('visibility', 'visible');
  610. }).mouseleave(
  611. function () {
  612. var element = $(this);
  613. element.css('border', 'none');
  614. button.css('visibility', 'hidden');
  615. })
  616. },
  617. isTextArea: false,
  618. textArea: Em.TextArea.extend({
  619. didInsertElement: function () {
  620. var element = $(this.get('element'));
  621. element.width($(this.get('parentView').get('element')).width() - 10);
  622. element.height($(this.get('parentView').get('element')).height());
  623. element.select();
  624. element.css('resize', 'none');
  625. },
  626. readOnly: true,
  627. value: function () {
  628. return this.get('content');
  629. }.property('content')
  630. })
  631. })
  632. });
  633. },
  634. /**
  635. * check warnings from server and put it in parsing
  636. */
  637. rerunChecks: function () {
  638. var self = this;
  639. var currentProgress = 0;
  640. var interval = setInterval(function () {
  641. currentProgress += 100000 / self.get('warningsTimeInterval');
  642. if (currentProgress < 100) {
  643. self.set('checksUpdateProgress', currentProgress);
  644. } else {
  645. clearInterval(interval);
  646. App.ajax.send({
  647. name: 'wizard.step3.rerun_checks',
  648. sender: self,
  649. success: 'rerunChecksSuccessCallback',
  650. error: 'rerunChecksErrorCallback'
  651. });
  652. }
  653. }, 1000);
  654. },
  655. rerunChecksSuccessCallback: function (data) {
  656. this.set('checksUpdateProgress', 100);
  657. this.set('checksUpdateStatus', 'SUCCESS');
  658. this.parseWarnings(data);
  659. },
  660. rerunChecksErrorCallback: function () {
  661. this.set('checksUpdateProgress', 100);
  662. this.set('checksUpdateStatus', 'FAILED');
  663. console.log('INFO: Getting host information(last_agent_env) from the server failed');
  664. },
  665. warnings: [],
  666. warningsByHost: [],
  667. warningsTimeInterval: 60000,
  668. /**
  669. * check are hosts have any warnings
  670. */
  671. isHostHaveWarnings: function(){
  672. return this.get('warnings.length') > 0;
  673. }.property('warnings'),
  674. isWarningsBoxVisible: function(){
  675. return (App.testMode) ? true : this.get('allHostsComplete');
  676. }.property('allHostsComplete'),
  677. checksUpdateProgress:0,
  678. checksUpdateStatus: null,
  679. /**
  680. * filter data for warnings parse
  681. * is data from host in bootStrap
  682. * @param data
  683. * @return {Object}
  684. */
  685. filterBootHosts: function (data) {
  686. var bootHostNames = this.get('bootHosts').mapProperty('name');
  687. var filteredData = {
  688. href: data.href,
  689. items: []
  690. };
  691. data.items.forEach(function (host) {
  692. if (bootHostNames.contains(host.Hosts.host_name)) {
  693. filteredData.items.push(host);
  694. }
  695. });
  696. return filteredData;
  697. },
  698. /**
  699. * parse warnings data for each host and total
  700. * @param data
  701. */
  702. parseWarnings: function (data) {
  703. data = App.testMode ? data : this.filterBootHosts(data);
  704. var warnings = [];
  705. var warning;
  706. var hosts = [];
  707. data.items.sort(function (a, b) {
  708. if (a.Hosts.host_name > b.Hosts.host_name) {
  709. return 1;
  710. }
  711. if (a.Hosts.host_name < b.Hosts.host_name) {
  712. return -1;
  713. }
  714. return 0;
  715. });
  716. data.items.forEach(function (_host) {
  717. var host = {
  718. name: _host.Hosts.host_name,
  719. warnings: []
  720. }
  721. if (!_host.Hosts.last_agent_env) {
  722. // in some unusual circumstances when last_agent_env is not available from the _host,
  723. // skip the _host and proceed to process the rest of the hosts.
  724. console.log("last_agent_env is missing for " + _host.Hosts.host_name + ". Skipping _host check.");
  725. return;
  726. }
  727. //parse all directories and files warnings for host
  728. //todo: to be removed after check in new API
  729. var stackFoldersAndFiles = _host.Hosts.last_agent_env.stackFoldersAndFiles || _host.Hosts.last_agent_env.paths;
  730. stackFoldersAndFiles.forEach(function (path) {
  731. warning = warnings.filterProperty('category', 'fileFolders').findProperty('name', path.name);
  732. if (warning) {
  733. warning.hosts.push(_host.Hosts.host_name);
  734. warning.onSingleHost = false;
  735. } else {
  736. warning = {
  737. name: path.name,
  738. hosts: [_host.Hosts.host_name],
  739. category: 'fileFolders',
  740. onSingleHost: true
  741. }
  742. warnings.push(warning);
  743. }
  744. host.warnings.push(warning);
  745. }, this);
  746. //parse all package warnings for host
  747. _host.Hosts.last_agent_env.installedPackages.forEach(function (_package) {
  748. warning = warnings.filterProperty('category', 'packages').findProperty('name', _package.name);
  749. if (warning) {
  750. warning.hosts.push(_host.Hosts.host_name);
  751. warning.version = _package.version,
  752. warning.onSingleHost = false;
  753. } else {
  754. warning = {
  755. name: _package.name,
  756. version: _package.version,
  757. hosts: [_host.Hosts.host_name],
  758. category: 'packages',
  759. onSingleHost: true
  760. }
  761. warnings.push(warning);
  762. }
  763. host.warnings.push(warning);
  764. }, this);
  765. //parse all process warnings for host
  766. //todo: to be removed after check in new API
  767. var javaProcs = _host.Hosts.last_agent_env.hostHealth ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs : _host.Hosts.last_agent_env.javaProcs;
  768. javaProcs.forEach(function (process) {
  769. warning = warnings.filterProperty('category', 'processes').findProperty('pid', process.pid);
  770. if (warning) {
  771. warning.hosts.push(_host.Hosts.host_name);
  772. warning.onSingleHost = false;
  773. } else {
  774. warning = {
  775. name: (process.command.substr(0, 35) + '...'),
  776. hosts: [_host.Hosts.host_name],
  777. category: 'processes',
  778. user: process.user,
  779. pid: process.pid,
  780. command: '<table><tr><td style="word-break: break-all;">' +
  781. ((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
  782. '<p style="text-align: center">................</p>' +
  783. '...' + process.command.substr(-230)) + '</td></tr></table>',
  784. onSingleHost: true
  785. }
  786. warnings.push(warning);
  787. }
  788. host.warnings.push(warning);
  789. }, this);
  790. //parse all service warnings for host
  791. //todo: to be removed after check in new API
  792. if (_host.Hosts.last_agent_env.hostHealth && _host.Hosts.last_agent_env.hostHealth.liveServices) {
  793. _host.Hosts.last_agent_env.hostHealth.liveServices.forEach(function (service) {
  794. if (service.status === 'Unhealthy') {
  795. warning = warnings.filterProperty('category', 'services').findProperty('name', service.name);
  796. if (warning) {
  797. warning.hosts.push(_host.Hosts.host_name);
  798. warning.onSingleHost = false;
  799. } else {
  800. warning = {
  801. name: service.name,
  802. hosts: [_host.Hosts.host_name],
  803. category: 'services',
  804. onSingleHost: true
  805. }
  806. warnings.push(warning);
  807. }
  808. host.warnings.push(warning);
  809. }
  810. }, this);
  811. }
  812. //parse all user warnings for host
  813. //todo: to be removed after check in new API
  814. if (_host.Hosts.last_agent_env.existingUsers) {
  815. _host.Hosts.last_agent_env.existingUsers.forEach(function (user) {
  816. warning = warnings.filterProperty('category', 'users').findProperty('name', user.userName);
  817. if (warning) {
  818. warning.hosts.push(_host.Hosts.host_name);
  819. warning.onSingleHost = false;
  820. } else {
  821. warning = {
  822. name: user.userName,
  823. hosts: [_host.Hosts.host_name],
  824. category: 'users',
  825. onSingleHost: true
  826. }
  827. warnings.push(warning);
  828. }
  829. host.warnings.push(warning);
  830. }, this);
  831. }
  832. //parse misc warnings for host
  833. var umask = _host.Hosts.last_agent_env.umask;
  834. if (umask && umask !== 18) {
  835. warning = warnings.filterProperty('category', 'misc').findProperty('name', umask);
  836. if (warning) {
  837. warning.hosts.push(_host.Hosts.host_name);
  838. warning.onSingleHost = false;
  839. } else {
  840. warning = {
  841. name: umask,
  842. hosts: [_host.Hosts.host_name],
  843. category: 'misc',
  844. onSingleHost: true
  845. }
  846. warnings.push(warning);
  847. }
  848. host.warnings.push(warning);
  849. }
  850. var firewallRunning = _host.Hosts.last_agent_env.iptablesIsRunning;
  851. if (firewallRunning!==null && firewallRunning) {
  852. var name = Em.I18n.t('installer.step3.hostWarningsPopup.firewall.name');
  853. warning = warnings.filterProperty('category', 'firewall').findProperty('name', name);
  854. if (warning) {
  855. warning.hosts.push(_host.Hosts.host_name);
  856. warning.onSingleHost = false;
  857. } else {
  858. warning = {
  859. name: name,
  860. hosts: [_host.Hosts.host_name],
  861. category: 'firewall',
  862. onSingleHost: true
  863. }
  864. warnings.push(warning);
  865. }
  866. host.warnings.push(warning);
  867. }
  868. hosts.push(host);
  869. }, this);
  870. warnings.forEach(function (warn) {
  871. if (warn.hosts.length < 11) {
  872. warn.hostsList = warn.hosts.join('<br>')
  873. } else {
  874. warn.hostsList = warn.hosts.slice(0,10).join('<br>') + '<br> ' + Em.I18n.t('installer.step3.hostWarningsPopup.moreHosts').format(warn.hosts.length - 10);
  875. }
  876. });
  877. hosts.unshift({
  878. name: 'All Hosts',
  879. warnings: warnings
  880. });
  881. this.set('warnings', warnings);
  882. this.set('warningsByHost', hosts);
  883. },
  884. /**
  885. * open popup that contain hosts' warnings
  886. * @param event
  887. */
  888. hostWarningsPopup: function(event){
  889. var self = this;
  890. var repoCategoryWarnings = this.get('repoCategoryWarnings');
  891. App.ModalPopup.show({
  892. header: Em.I18n.t('installer.step3.warnings.popup.header'),
  893. secondary: Em.I18n.t('installer.step3.hostWarningsPopup.rerunChecks'),
  894. primary: Em.I18n.t('common.close'),
  895. onPrimary: function () {
  896. self.set('checksUpdateStatus', null);
  897. this.hide();
  898. },
  899. onClose: function(){
  900. self.set('checksUpdateStatus', null);
  901. this.hide();
  902. },
  903. onSecondary: function() {
  904. self.rerunChecks();
  905. },
  906. didInsertElement: function () {
  907. this.fitHeight();
  908. },
  909. footerClass: Ember.View.extend({
  910. template: Ember.Handlebars.compile([
  911. '<div class="update-progress pull-left">',
  912. '{{#if view.isUpdateInProgress}}',
  913. '<div class="progress-info active progress">',
  914. '<div class="bar" {{bindAttr style="view.progressWidth"}}></div></div>',
  915. '{{else}}<label {{bindAttr class="view.updateStatusClass"}}>{{view.updateStatus}}</label>',
  916. '{{/if}}</div>',
  917. '{{#if view.parentView.secondary}}<button type="button" class="btn btn-info" {{bindAttr disabled="view.isUpdateInProgress"}} {{action onSecondary target="view.parentView"}}><i class="icon-repeat"></i>&nbsp;{{view.parentView.secondary}}</button>{{/if}}',
  918. '{{#if view.parentView.primary}}<button type="button" class="btn" {{action onPrimary target="view.parentView"}}>{{view.parentView.primary}}</button>{{/if}}'
  919. ].join('')),
  920. classNames: ['modal-footer', 'host-checks-update'],
  921. progressWidth: function(){
  922. return 'width:'+App.router.get('wizardStep3Controller.checksUpdateProgress')+'%';
  923. }.property('App.router.wizardStep3Controller.checksUpdateProgress'),
  924. isUpdateInProgress: function(){
  925. if((App.router.get('wizardStep3Controller.checksUpdateProgress') > 0) &&
  926. (App.router.get('wizardStep3Controller.checksUpdateProgress') < 100)){
  927. return true;
  928. }
  929. }.property('App.router.wizardStep3Controller.checksUpdateProgress'),
  930. updateStatusClass:function(){
  931. var status = App.router.get('wizardStep3Controller.checksUpdateStatus');
  932. if(status === 'SUCCESS'){
  933. return 'text-success';
  934. } else if(status === 'FAILED'){
  935. return 'text-error';
  936. } else {
  937. return null;
  938. }
  939. }.property('App.router.wizardStep3Controller.checksUpdateStatus'),
  940. updateStatus:function(){
  941. var status = App.router.get('wizardStep3Controller.checksUpdateStatus');
  942. if(status === 'SUCCESS'){
  943. return Em.I18n.t('installer.step3.warnings.updateChecks.success');
  944. } else if(status === 'FAILED'){
  945. return Em.I18n.t('installer.step3.warnings.updateChecks.failed');
  946. } else {
  947. return null;
  948. }
  949. }.property('App.router.wizardStep3Controller.checksUpdateStatus')
  950. }),
  951. bodyClass: Ember.View.extend({
  952. templateName: require('templates/wizard/step3_host_warnings_popup'),
  953. classNames: ['host-check'],
  954. didInsertElement: function () {
  955. Ember.run.next(this, function () {
  956. App.tooltip(this.$("[rel='HostsListTooltip']"), {html: true, placement: "right"});
  957. App.tooltip(this.$('#process .warning-name'), {html: true, placement: "top"});
  958. })
  959. }.observes('content'),
  960. warningsByHost: function () {
  961. return App.router.get('wizardStep3Controller.warningsByHost');
  962. }.property('App.router.wizardStep3Controller.warningsByHost'),
  963. warnings: function () {
  964. return App.router.get('wizardStep3Controller.warnings');
  965. }.property('App.router.wizardStep3Controller.warnings'),
  966. categories: function () {
  967. return this.get('warningsByHost').mapProperty('name');
  968. }.property('warningsByHost'),
  969. category: 'All Hosts',
  970. categoryWarnings: function () {
  971. return this.get('warningsByHost').findProperty('name', this.get('category')).warnings
  972. }.property('warningsByHost', 'category'),
  973. content: function () {
  974. var categoryWarnings = this.get('categoryWarnings');
  975. return [
  976. Ember.Object.create({
  977. warnings: repoCategoryWarnings,
  978. title: Em.I18n.t('installer.step3.hostWarningsPopup.repositories'),
  979. message: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.message'),
  980. type: Em.I18n.t('common.issues'),
  981. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.repositories'),
  982. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.invalid'),
  983. category: 'repositories'
  984. }),
  985. Ember.Object.create({
  986. warnings: categoryWarnings.filterProperty('category', 'firewall'),
  987. title: Em.I18n.t('installer.step3.hostWarningsPopup.firewall'),
  988. message: Em.I18n.t('installer.step3.hostWarningsPopup.firewall.message'),
  989. type: Em.I18n.t('common.issues'),
  990. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.firewall'),
  991. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
  992. category: 'firewall'
  993. }),
  994. Ember.Object.create({
  995. warnings: categoryWarnings.filterProperty('category', 'processes'),
  996. title: Em.I18n.t('installer.step3.hostWarningsPopup.process'),
  997. message: Em.I18n.t('installer.step3.hostWarningsPopup.processes.message'),
  998. type: Em.I18n.t('common.process'),
  999. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.processes'),
  1000. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
  1001. category: 'process'
  1002. }),
  1003. Ember.Object.create({
  1004. warnings: categoryWarnings.filterProperty('category', 'packages'),
  1005. title: Em.I18n.t('installer.step3.hostWarningsPopup.package'),
  1006. message: Em.I18n.t('installer.step3.hostWarningsPopup.packages.message'),
  1007. type: Em.I18n.t('common.package'),
  1008. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.packages'),
  1009. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.installed'),
  1010. category: 'package'
  1011. }),
  1012. Ember.Object.create({
  1013. warnings: categoryWarnings.filterProperty('category', 'fileFolders'),
  1014. title: Em.I18n.t('installer.step3.hostWarningsPopup.fileAndFolder'),
  1015. message: Em.I18n.t('installer.step3.hostWarningsPopup.fileFolders.message'),
  1016. type: Em.I18n.t('common.path'),
  1017. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.filesAndFolders'),
  1018. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1019. category: 'fileFolders'
  1020. }),
  1021. Ember.Object.create({
  1022. warnings: categoryWarnings.filterProperty('category', 'services'),
  1023. title: Em.I18n.t('installer.step3.hostWarningsPopup.service'),
  1024. message: Em.I18n.t('installer.step3.hostWarningsPopup.services.message'),
  1025. type: Em.I18n.t('common.service'),
  1026. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.services'),
  1027. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.notRunning'),
  1028. category: 'service'
  1029. }),
  1030. Ember.Object.create({
  1031. warnings: categoryWarnings.filterProperty('category', 'users'),
  1032. title: Em.I18n.t('installer.step3.hostWarningsPopup.user'),
  1033. message: Em.I18n.t('installer.step3.hostWarningsPopup.users.message'),
  1034. type: Em.I18n.t('common.user'),
  1035. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.users'),
  1036. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1037. category: 'user'
  1038. }),
  1039. Ember.Object.create({
  1040. warnings: categoryWarnings.filterProperty('category', 'misc'),
  1041. title: Em.I18n.t('installer.step3.hostWarningsPopup.misc'),
  1042. message: Em.I18n.t('installer.step3.hostWarningsPopup.misc.message'),
  1043. type: Em.I18n.t('installer.step3.hostWarningsPopup.misc.umask'),
  1044. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.misc'),
  1045. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1046. category: 'misc'
  1047. })
  1048. ]
  1049. }.property('category', 'warningsByHost'),
  1050. showHostsPopup: function (hosts) {
  1051. $('.tooltip').hide();
  1052. App.ModalPopup.show({
  1053. header: Em.I18n.t('installer.step3.hostWarningsPopup.allHosts'),
  1054. bodyClass: Ember.View.extend({
  1055. hosts: hosts.context,
  1056. template: Ember.Handlebars.compile('<ul>{{#each host in view.hosts}}<li>{{host}}</li>{{/each}}</ul>')
  1057. }),
  1058. onPrimary: function () {
  1059. this.hide();
  1060. },
  1061. secondary: null
  1062. });
  1063. },
  1064. onToggleBlock: function (category) {
  1065. this.$('#' + category.context.category).toggle('blind', 500);
  1066. },
  1067. warningsNotice: function () {
  1068. var warnings = this.get('warnings');
  1069. var warningsByHost = self.get('warningsByHost').slice();
  1070. warningsByHost.shift();
  1071. var issuesNumber = warnings.length + repoCategoryWarnings.length;
  1072. var issues = issuesNumber + ' ' + (issuesNumber.length === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.issue') : Em.I18n.t('installer.step3.hostWarningsPopup.issues'));
  1073. var repoHostsNumber = (repoCategoryWarnings.length > 0 ? repoCategoryWarnings[0].hosts.length : 0);
  1074. var hostsNumber = repoHostsNumber + warningsByHost.length - warningsByHost.filterProperty('warnings.length', 0).length;
  1075. var hosts = hostsNumber + ' ' + (hostsNumber === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.host') : Em.I18n.t('installer.step3.hostWarningsPopup.hosts'));
  1076. return Em.I18n.t('installer.step3.hostWarningsPopup.summary').format(issues, hosts);
  1077. }.property('warnings', 'warningsByHost'),
  1078. /**
  1079. * generate detailed content to show it in new window
  1080. */
  1081. contentInDetails: function () {
  1082. var content = this.get('content');
  1083. var warningsByHost = this.get('warningsByHost').slice();
  1084. warningsByHost.shift();
  1085. var newContent = '';
  1086. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.header') + new Date;
  1087. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.hosts');
  1088. newContent += warningsByHost.filterProperty('warnings.length').mapProperty('name').join(' ');
  1089. if (content.findProperty('category', 'fileFolders').warnings.length) {
  1090. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.fileFolders');
  1091. newContent += content.findProperty('category', 'fileFolders').warnings.mapProperty('name').join(' ');
  1092. }
  1093. if (content.findProperty('category', 'process').warnings.length) {
  1094. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.process');
  1095. content.findProperty('category', 'process').warnings.forEach(function (process, i) {
  1096. process.hosts.forEach(function (host, j) {
  1097. if (!!i || !!j) {
  1098. newContent += ',';
  1099. }
  1100. newContent += '(' + host + ',' + process.user + ',' + process.pid + ')';
  1101. });
  1102. });
  1103. }
  1104. if (content.findProperty('category', 'package').warnings.length) {
  1105. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.package');
  1106. newContent += content.findProperty('category', 'package').warnings.mapProperty('name').join(' ');
  1107. }
  1108. if (content.findProperty('category', 'service').warnings.length) {
  1109. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.service');
  1110. newContent += content.findProperty('category', 'service').warnings.mapProperty('name').join(' ');
  1111. }
  1112. if (content.findProperty('category', 'user').warnings.length) {
  1113. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.user');
  1114. newContent += content.findProperty('category', 'user').warnings.mapProperty('name').join(' ');
  1115. }
  1116. newContent += '</p>';
  1117. return newContent;
  1118. }.property('content', 'warningsByHost'),
  1119. /**
  1120. * open new browser tab with detailed content
  1121. */
  1122. openWarningsInDialog: function(){
  1123. var newWindow = window.open('');
  1124. var newDocument = newWindow.document;
  1125. newDocument.write(this.get('contentInDetails'));
  1126. newWindow.focus();
  1127. }
  1128. })
  1129. })
  1130. },
  1131. registeredHostsPopup: function(){
  1132. var self = this;
  1133. App.ModalPopup.show({
  1134. header: Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('registeredHosts').length),
  1135. secondary: null,
  1136. bodyClass: Ember.View.extend({
  1137. template: Ember.Handlebars.compile([
  1138. '<p>{{view.message}}</p>',
  1139. '<ul>{{#each host in view.registeredHosts}}',
  1140. '<li>{{host}}</li>',
  1141. '{{/each}}</ul>'
  1142. ].join('')),
  1143. message: Em.I18n.t('installer.step3.registeredHostsPopup'),
  1144. registeredHosts: self.get('registeredHosts')
  1145. })
  1146. })
  1147. },
  1148. back: function () {
  1149. if (this.get('isInstallInProgress')) {
  1150. return;
  1151. }
  1152. App.router.send('back');
  1153. }
  1154. });