step3_controller.js 49 KB

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