step3_controller.js 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  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. alternativeWarnings: {}
  706. };
  707. data.items.sortPropertyLight('Hosts.host_name').forEach(function (_host) {
  708. var host = {
  709. name: _host.Hosts.host_name,
  710. warnings: []
  711. };
  712. if (!_host.Hosts.last_agent_env) {
  713. // in some unusual circumstances when last_agent_env is not available from the _host,
  714. // skip the _host and proceed to process the rest of the hosts.
  715. console.log("last_agent_env is missing for " + _host.Hosts.host_name + ". Skipping _host check.");
  716. return;
  717. }
  718. //parse all directories and files warnings for host
  719. //todo: to be removed after check in new API
  720. var stackFoldersAndFiles = _host.Hosts.last_agent_env.stackFoldersAndFiles || [];
  721. stackFoldersAndFiles.forEach(function (path) {
  722. warning = warningCategories.fileFoldersWarnings[path.name];
  723. if (warning) {
  724. warning.hosts.push(_host.Hosts.host_name);
  725. warning.onSingleHost = false;
  726. } else {
  727. warningCategories.fileFoldersWarnings[path.name] = warning = {
  728. name: path.name,
  729. hosts: [_host.Hosts.host_name],
  730. category: 'fileFolders',
  731. onSingleHost: true
  732. };
  733. }
  734. host.warnings.push(warning);
  735. }, this);
  736. //parse all package warnings for host
  737. _host.Hosts.last_agent_env.installedPackages.forEach(function (_package) {
  738. warning = warningCategories.packagesWarnings[_package.name];
  739. if (warning) {
  740. warning.hosts.push(_host.Hosts.host_name);
  741. warning.version = _package.version;
  742. warning.onSingleHost = false;
  743. } else {
  744. warningCategories.packagesWarnings[_package.name] = warning = {
  745. name: _package.name,
  746. version: _package.version,
  747. hosts: [_host.Hosts.host_name],
  748. category: 'packages',
  749. onSingleHost: true
  750. };
  751. }
  752. host.warnings.push(warning);
  753. }, this);
  754. //parse all process warnings for host
  755. //todo: to be removed after check in new API
  756. var javaProcs = _host.Hosts.last_agent_env.hostHealth ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs : _host.Hosts.last_agent_env.javaProcs;
  757. javaProcs.forEach(function (process) {
  758. warning = warningCategories.processesWarnings[process.pid];
  759. if (warning) {
  760. warning.hosts.push(_host.Hosts.host_name);
  761. warning.onSingleHost = false;
  762. } else {
  763. warningCategories.processesWarnings[process.pid] = warning = {
  764. name: (process.command.substr(0, 35) + '...'),
  765. hosts: [_host.Hosts.host_name],
  766. category: 'processes',
  767. user: process.user,
  768. pid: process.pid,
  769. command: '<table><tr><td style="word-break: break-all;">' +
  770. ((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
  771. '<p style="text-align: center">................</p>' +
  772. '...' + process.command.substr(-230)) + '</td></tr></table>',
  773. onSingleHost: true
  774. };
  775. }
  776. host.warnings.push(warning);
  777. }, this);
  778. //parse all service warnings for host
  779. //todo: to be removed after check in new API
  780. if (_host.Hosts.last_agent_env.hostHealth && _host.Hosts.last_agent_env.hostHealth.liveServices) {
  781. _host.Hosts.last_agent_env.hostHealth.liveServices.forEach(function (service) {
  782. if (service.status === 'Unhealthy') {
  783. warning = warningCategories.servicesWarnings[service.name];
  784. if (warning) {
  785. warning.hosts.push(_host.Hosts.host_name);
  786. warning.onSingleHost = false;
  787. } else {
  788. warningCategories.servicesWarnings[service.name] = warning = {
  789. name: service.name,
  790. hosts: [_host.Hosts.host_name],
  791. category: 'services',
  792. onSingleHost: true
  793. };
  794. }
  795. host.warnings.push(warning);
  796. }
  797. }, this);
  798. }
  799. //parse all user warnings for host
  800. //todo: to be removed after check in new API
  801. if (_host.Hosts.last_agent_env.existingUsers) {
  802. _host.Hosts.last_agent_env.existingUsers.forEach(function (user) {
  803. warning = warningCategories.usersWarnings[user.userName];
  804. if (warning) {
  805. warning.hosts.push(_host.Hosts.host_name);
  806. warning.onSingleHost = false;
  807. } else {
  808. warningCategories.usersWarnings[user.userName] = warning = {
  809. name: user.userName,
  810. hosts: [_host.Hosts.host_name],
  811. category: 'users',
  812. onSingleHost: true
  813. };
  814. }
  815. host.warnings.push(warning);
  816. }, this);
  817. }
  818. //parse misc warnings for host
  819. var umask = _host.Hosts.last_agent_env.umask;
  820. if (umask && umask !== 18) {
  821. warning = warnings.filterProperty('category', 'misc').findProperty('name', umask);
  822. if (warning) {
  823. warning.hosts.push(_host.Hosts.host_name);
  824. warning.onSingleHost = false;
  825. } else {
  826. warning = {
  827. name: umask,
  828. hosts: [_host.Hosts.host_name],
  829. category: 'misc',
  830. onSingleHost: true
  831. };
  832. warnings.push(warning);
  833. }
  834. host.warnings.push(warning);
  835. }
  836. var firewallRunning = _host.Hosts.last_agent_env.iptablesIsRunning;
  837. if (firewallRunning!==null && firewallRunning) {
  838. var name = Em.I18n.t('installer.step3.hostWarningsPopup.firewall.name');
  839. warning = warnings.filterProperty('category', 'firewall').findProperty('name', name);
  840. if (warning) {
  841. warning.hosts.push(_host.Hosts.host_name);
  842. warning.onSingleHost = false;
  843. } else {
  844. warning = {
  845. name: name,
  846. hosts: [_host.Hosts.host_name],
  847. category: 'firewall',
  848. onSingleHost: true
  849. };
  850. warnings.push(warning);
  851. }
  852. host.warnings.push(warning);
  853. }
  854. if (_host.Hosts.last_agent_env.alternatives) {
  855. _host.Hosts.last_agent_env.alternatives.forEach(function (alternative) {
  856. warning = warningCategories.alternativeWarnings[alternative.name];
  857. if (warning) {
  858. warning.hosts.push(_host.Hosts.host_name);
  859. warning.onSingleHost = false;
  860. } else {
  861. warningCategories.alternativeWarnings[alternative.name] = warning = {
  862. name: alternative.name,
  863. target: alternative.target,
  864. hosts: [_host.Hosts.host_name],
  865. category: 'alternatives',
  866. onSingleHost: false
  867. };
  868. }
  869. host.warnings.push(warning);
  870. }, this);
  871. }
  872. hosts.push(host);
  873. }, this);
  874. for (var categoryId in warningCategories) {
  875. var category = warningCategories[categoryId]
  876. for (var warningId in category) {
  877. warnings.push(category[warningId]);
  878. }
  879. }
  880. warnings.forEach(function (warn) {
  881. if (warn.hosts.length < 11) {
  882. warn.hostsList = warn.hosts.join('<br>')
  883. } else {
  884. warn.hostsList = warn.hosts.slice(0,10).join('<br>') + '<br> ' + Em.I18n.t('installer.step3.hostWarningsPopup.moreHosts').format(warn.hosts.length - 10);
  885. }
  886. });
  887. hosts.unshift({
  888. name: 'All Hosts',
  889. warnings: warnings
  890. });
  891. this.set('warnings', warnings);
  892. this.set('warningsByHost', hosts);
  893. this.set('isWarningsLoaded', true);
  894. },
  895. /**
  896. * open popup that contain hosts' warnings
  897. * @param event
  898. */
  899. hostWarningsPopup: function(event){
  900. var self = this;
  901. var repoCategoryWarnings = this.get('repoCategoryWarnings');
  902. var diskCategoryWarnings = this.get('diskCategoryWarnings');
  903. App.ModalPopup.show({
  904. header: Em.I18n.t('installer.step3.warnings.popup.header'),
  905. secondary: Em.I18n.t('installer.step3.hostWarningsPopup.rerunChecks'),
  906. primary: Em.I18n.t('common.close'),
  907. onPrimary: function () {
  908. self.set('checksUpdateStatus', null);
  909. this.hide();
  910. },
  911. onClose: function(){
  912. self.set('checksUpdateStatus', null);
  913. this.hide();
  914. },
  915. onSecondary: function() {
  916. self.rerunChecks();
  917. },
  918. didInsertElement: function () {
  919. this.fitHeight();
  920. },
  921. footerClass: Ember.View.extend({
  922. templateName: require('templates/wizard/step3_host_warning_popup_footer'),
  923. classNames: ['modal-footer', 'host-checks-update'],
  924. footerControllerBinding: 'App.router.wizardStep3Controller',
  925. progressWidth: function(){
  926. return 'width:'+this.get('footerController.checksUpdateProgress')+'%';
  927. }.property('footerController.checksUpdateProgress'),
  928. isUpdateInProgress: function(){
  929. if((this.get('footerController.checksUpdateProgress') > 0) &&
  930. (this.get('footerController.checksUpdateProgress') < 100)){
  931. return true;
  932. }
  933. }.property('footerController.checksUpdateProgress'),
  934. updateStatusClass:function(){
  935. var status = this.get('footerController.checksUpdateStatus');
  936. if(status === 'SUCCESS'){
  937. return 'text-success';
  938. } else if(status === 'FAILED'){
  939. return 'text-error';
  940. } else {
  941. return null;
  942. }
  943. }.property('footerController.checksUpdateStatus'),
  944. updateStatus:function(){
  945. var status = this.get('footerController.checksUpdateStatus');
  946. if(status === 'SUCCESS'){
  947. return Em.I18n.t('installer.step3.warnings.updateChecks.success');
  948. } else if(status === 'FAILED'){
  949. return Em.I18n.t('installer.step3.warnings.updateChecks.failed');
  950. } else {
  951. return null;
  952. }
  953. }.property('footerController.checksUpdateStatus')
  954. }),
  955. bodyClass: Ember.View.extend({
  956. templateName: require('templates/wizard/step3_host_warnings_popup'),
  957. classNames: ['host-check'],
  958. bodyControllerBinding: 'App.router.wizardStep3Controller',
  959. didInsertElement: function () {
  960. Ember.run.next(this, function () {
  961. App.tooltip(this.$("[rel='HostsListTooltip']"), {html: true, placement: "right"});
  962. App.tooltip(this.$('#process .warning-name'), {html: true, placement: "top"});
  963. });
  964. }.observes('content'),
  965. hostSelectView: Ember.Select.extend({
  966. //content has default value "All Hosts" to bind selection to category
  967. content: ['All Hosts'],
  968. hosts: function () {
  969. return this.get('parentView.warningsByHost').mapProperty('name');
  970. }.property('parentView.warningsByHost'),
  971. isLoaded: false,
  972. selectionBinding: "parentView.category",
  973. didInsertElement: function(){
  974. this.initContent();
  975. },
  976. initContent: function () {
  977. this.set('isLoaded', false);
  978. //The lazy loading for select elements supported only by Firefox and Chrome
  979. var isBrowserSupported = $.browser.mozilla || ($.browser.safari && navigator.userAgent.indexOf('Chrome') !== -1);
  980. var isLazyLoading = isBrowserSupported && this.get('hosts').length > 100;
  981. this.set('isLazyLoading', isLazyLoading);
  982. if (isLazyLoading) {
  983. //select need at least 30 hosts to have scrollbar
  984. this.set('content', this.get('hosts').slice(0, 30));
  985. } else {
  986. this.set('content', this.get('hosts'));
  987. this.set('isLoaded', true);
  988. }
  989. }.observes('parentView.warningsByHost'),
  990. /**
  991. * on click start lazy loading
  992. */
  993. click: function () {
  994. if (!this.get('isLoaded') && this.get('isLazyLoading')) {
  995. //filter out hosts, which already pushed in select
  996. var source = this.get('hosts').filter(function (_host) {
  997. return !this.get('content').contains(_host);
  998. }, this).slice();
  999. lazyloading.run({
  1000. destination: this.get('content'),
  1001. source: source,
  1002. context: this,
  1003. initSize: 30,
  1004. chunkSize: 200,
  1005. delay: 50
  1006. });
  1007. }
  1008. }
  1009. }),
  1010. warningsByHost: function () {
  1011. return this.get('bodyController.warningsByHost');
  1012. }.property('bodyController.warningsByHost'),
  1013. warnings: function () {
  1014. return this.get('bodyController.warnings');
  1015. }.property('bodyController.warnings'),
  1016. category: 'All Hosts',
  1017. categoryWarnings: function () {
  1018. return this.get('warningsByHost').findProperty('name', this.get('category')).warnings
  1019. }.property('warningsByHost', 'category'),
  1020. content: function () {
  1021. var categoryWarnings = this.get('categoryWarnings');
  1022. return [
  1023. Ember.Object.create({
  1024. warnings: diskCategoryWarnings,
  1025. title: Em.I18n.t('installer.step3.hostWarningsPopup.disk'),
  1026. message: Em.I18n.t('installer.step3.hostWarningsPopup.disk.message'),
  1027. type: Em.I18n.t('common.issues'),
  1028. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.disk'),
  1029. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1030. category: 'disk',
  1031. isCollapsed: true
  1032. }),
  1033. Ember.Object.create({
  1034. warnings: repoCategoryWarnings,
  1035. title: Em.I18n.t('installer.step3.hostWarningsPopup.repositories'),
  1036. message: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.message'),
  1037. type: Em.I18n.t('common.issues'),
  1038. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.repositories'),
  1039. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.invalid'),
  1040. category: 'repositories',
  1041. isCollapsed: true
  1042. }),
  1043. Ember.Object.create({
  1044. warnings: categoryWarnings.filterProperty('category', 'firewall'),
  1045. title: Em.I18n.t('installer.step3.hostWarningsPopup.firewall'),
  1046. message: Em.I18n.t('installer.step3.hostWarningsPopup.firewall.message'),
  1047. type: Em.I18n.t('common.issues'),
  1048. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.firewall'),
  1049. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
  1050. category: 'firewall',
  1051. isCollapsed: true
  1052. }),
  1053. Ember.Object.create({
  1054. warnings: categoryWarnings.filterProperty('category', 'processes'),
  1055. title: Em.I18n.t('installer.step3.hostWarningsPopup.process'),
  1056. message: Em.I18n.t('installer.step3.hostWarningsPopup.processes.message'),
  1057. type: Em.I18n.t('common.process'),
  1058. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.processes'),
  1059. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.running'),
  1060. category: 'process',
  1061. isCollapsed: true
  1062. }),
  1063. Ember.Object.create({
  1064. warnings: categoryWarnings.filterProperty('category', 'packages'),
  1065. title: Em.I18n.t('installer.step3.hostWarningsPopup.package'),
  1066. message: Em.I18n.t('installer.step3.hostWarningsPopup.packages.message'),
  1067. type: Em.I18n.t('common.package'),
  1068. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.packages'),
  1069. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.installed'),
  1070. category: 'package',
  1071. isCollapsed: true
  1072. }),
  1073. Ember.Object.create({
  1074. warnings: categoryWarnings.filterProperty('category', 'fileFolders'),
  1075. title: Em.I18n.t('installer.step3.hostWarningsPopup.fileAndFolder'),
  1076. message: Em.I18n.t('installer.step3.hostWarningsPopup.fileFolders.message'),
  1077. type: Em.I18n.t('common.path'),
  1078. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.filesAndFolders'),
  1079. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1080. category: 'fileFolders',
  1081. isCollapsed: true
  1082. }),
  1083. Ember.Object.create({
  1084. warnings: categoryWarnings.filterProperty('category', 'services'),
  1085. title: Em.I18n.t('installer.step3.hostWarningsPopup.service'),
  1086. message: Em.I18n.t('installer.step3.hostWarningsPopup.services.message'),
  1087. type: Em.I18n.t('common.service'),
  1088. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.services'),
  1089. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.notRunning'),
  1090. category: 'service',
  1091. isCollapsed: true
  1092. }),
  1093. Ember.Object.create({
  1094. warnings: categoryWarnings.filterProperty('category', 'users'),
  1095. title: Em.I18n.t('installer.step3.hostWarningsPopup.user'),
  1096. message: Em.I18n.t('installer.step3.hostWarningsPopup.users.message'),
  1097. type: Em.I18n.t('common.user'),
  1098. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.users'),
  1099. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1100. category: 'user',
  1101. isCollapsed: true
  1102. }),
  1103. Ember.Object.create({
  1104. warnings: categoryWarnings.filterProperty('category', 'misc'),
  1105. title: Em.I18n.t('installer.step3.hostWarningsPopup.misc'),
  1106. message: Em.I18n.t('installer.step3.hostWarningsPopup.misc.message'),
  1107. type: Em.I18n.t('installer.step3.hostWarningsPopup.misc.umask'),
  1108. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.empty.misc'),
  1109. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1110. category: 'misc',
  1111. isCollapsed: true
  1112. }),
  1113. Ember.Object.create({
  1114. warnings: categoryWarnings.filterProperty('category', 'alternatives'),
  1115. title: Em.I18n.t('installer.step3.hostWarningsPopup.alternatives'),
  1116. message: Em.I18n.t('installer.step3.hostWarningsPopup.alternatives.message'),
  1117. type: Em.I18n.t('installer.step3.hostWarningsPopup.alternatives.umask'),
  1118. emptyName: Em.I18n.t('installer.step3.hostWarningsPopup.alternatives.emptyinstaller.step3.hostWarningsPopup.alternatives.empty'),
  1119. action: Em.I18n.t('installer.step3.hostWarningsPopup.action.exists'),
  1120. category: 'alternatives',
  1121. isCollapsed: true
  1122. })
  1123. ]
  1124. }.property('category', 'warningsByHost'),
  1125. showHostsPopup: function (hosts) {
  1126. $('.tooltip').hide();
  1127. App.ModalPopup.show({
  1128. header: Em.I18n.t('installer.step3.hostWarningsPopup.allHosts'),
  1129. bodyClass: Ember.View.extend({
  1130. hosts: hosts.context,
  1131. template: Ember.Handlebars.compile('<ul>{{#each host in view.hosts}}<li>{{host}}</li>{{/each}}</ul>')
  1132. }),
  1133. secondary: null
  1134. });
  1135. },
  1136. onToggleBlock: function (category) {
  1137. this.$('#' + category.context.category).toggle('blind', 500);
  1138. category.context.set("isCollapsed", !category.context.get("isCollapsed"));
  1139. },
  1140. /**
  1141. * generate number of hosts which had warnings, avoid duplicated host names in different warnings.
  1142. */
  1143. warningHostsNamesCount: function () {
  1144. var hostNameMap = Ember.Object.create();
  1145. var warningsByHost = self.get('warningsByHost').slice();
  1146. warningsByHost.shift();
  1147. warningsByHost.forEach( function( _host) {
  1148. if (_host.warnings.length) {
  1149. hostNameMap[_host.name] = true;
  1150. }
  1151. })
  1152. if (repoCategoryWarnings.length) {
  1153. repoCategoryWarnings[0].hostsNames.forEach(function (_hostName) {
  1154. if (!hostNameMap[_hostName]) {
  1155. hostNameMap[_hostName] = true;
  1156. }
  1157. })
  1158. }
  1159. if (diskCategoryWarnings.length) {
  1160. diskCategoryWarnings[0].hostsNames.forEach(function (_hostName) {
  1161. if (!hostNameMap[_hostName]) {
  1162. hostNameMap[_hostName] = true;
  1163. }
  1164. })
  1165. }
  1166. var size = 0;
  1167. for (var key in hostNameMap) {
  1168. if (hostNameMap.hasOwnProperty(key)) size++;
  1169. }
  1170. return size;
  1171. },
  1172. warningsNotice: function () {
  1173. var warnings = this.get('warnings');
  1174. var issuesNumber = warnings.length + repoCategoryWarnings.length + diskCategoryWarnings.length;
  1175. var issues = issuesNumber + ' ' + (issuesNumber.length === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.issue') : Em.I18n.t('installer.step3.hostWarningsPopup.issues'));
  1176. var hostsCnt = this.warningHostsNamesCount();
  1177. var hosts = hostsCnt + ' ' + (hostsCnt === 1 ? Em.I18n.t('installer.step3.hostWarningsPopup.host') : Em.I18n.t('installer.step3.hostWarningsPopup.hosts'));
  1178. return Em.I18n.t('installer.step3.hostWarningsPopup.summary').format(issues, hosts);
  1179. }.property('warnings', 'warningsByHost'),
  1180. /**
  1181. * generate detailed content to show it in new window
  1182. */
  1183. contentInDetails: function () {
  1184. var content = this.get('content');
  1185. var warningsByHost = this.get('warningsByHost').slice();
  1186. warningsByHost.shift();
  1187. var newContent = '';
  1188. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.header') + new Date;
  1189. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.hosts');
  1190. newContent += warningsByHost.filterProperty('warnings.length').mapProperty('name').join(' ');
  1191. if (content.findProperty('category', 'firewall').warnings.length) {
  1192. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.firewall');
  1193. newContent += content.findProperty('category', 'firewall').warnings.mapProperty('name').join('<br>');
  1194. }
  1195. if (content.findProperty('category', 'fileFolders').warnings.length) {
  1196. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.fileFolders');
  1197. newContent += content.findProperty('category', 'fileFolders').warnings.mapProperty('name').join(' ');
  1198. }
  1199. if (content.findProperty('category', 'process').warnings.length) {
  1200. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.process');
  1201. content.findProperty('category', 'process').warnings.forEach(function (process, i) {
  1202. process.hosts.forEach(function (host, j) {
  1203. if (!!i || !!j) {
  1204. newContent += ',';
  1205. }
  1206. newContent += '(' + host + ',' + process.user + ',' + process.pid + ')';
  1207. });
  1208. });
  1209. }
  1210. if (content.findProperty('category', 'package').warnings.length) {
  1211. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.package');
  1212. newContent += content.findProperty('category', 'package').warnings.mapProperty('name').join(' ');
  1213. }
  1214. if (content.findProperty('category', 'service').warnings.length) {
  1215. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.service');
  1216. newContent += content.findProperty('category', 'service').warnings.mapProperty('name').join(' ');
  1217. }
  1218. if (content.findProperty('category', 'user').warnings.length) {
  1219. newContent += Em.I18n.t('installer.step3.hostWarningsPopup.report.user');
  1220. newContent += content.findProperty('category', 'user').warnings.mapProperty('name').join(' ');
  1221. }
  1222. newContent += '</p>';
  1223. return newContent;
  1224. }.property('content', 'warningsByHost'),
  1225. /**
  1226. * open new browser tab with detailed content
  1227. */
  1228. openWarningsInDialog: function(){
  1229. var newWindow = window.open('');
  1230. var newDocument = newWindow.document;
  1231. newDocument.write(this.get('contentInDetails'));
  1232. newWindow.focus();
  1233. }
  1234. })
  1235. })
  1236. },
  1237. registeredHostsPopup: function(){
  1238. var self = this;
  1239. App.ModalPopup.show({
  1240. header: Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('registeredHosts').length),
  1241. secondary: null,
  1242. bodyClass: Ember.View.extend({
  1243. templateName: require('templates/wizard/step3_registered_hosts_popup'),
  1244. message: Em.I18n.t('installer.step3.registeredHostsPopup'),
  1245. registeredHosts: self.get('registeredHosts')
  1246. })
  1247. })
  1248. }
  1249. });