step6_controller.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  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 blueprintUtils = require('utils/blueprint');
  20. var validationUtils = require('utils/validator');
  21. /**
  22. * By Step 6, we have the following information stored in App.db and set on this
  23. * controller by the router:
  24. *
  25. * hosts: App.db.hosts (list of all hosts the user selected in Step 3)
  26. * selectedServiceNames: App.db.selectedServiceNames (the services that the user selected in Step 4)
  27. * masterComponentHosts: App.db.masterComponentHosts (master-components-to-hosts mapping the user selected in Step 5)
  28. *
  29. * Step 6 will set the following information in App.db:
  30. * slaveComponentHosts: App.db.slaveComponentHosts (slave-components-to-hosts mapping the user selected in Step 6)
  31. *
  32. */
  33. App.WizardStep6Controller = Em.Controller.extend(App.BlueprintMixin, {
  34. name: 'wizardStep6Controller',
  35. /**
  36. * List of hosts
  37. * @type {object[]}
  38. */
  39. hosts: [],
  40. /**
  41. * List of components info about selecting/deselecting status for components.
  42. *
  43. * @type {Array}
  44. * @item {Em.Object}
  45. * @property name {String} - component name
  46. * @property label {String} - component display name
  47. * @property allChecked {bool} - all checkboxes are checked
  48. * @property noChecked {bool} - no checkboxes checked
  49. */
  50. headers: [],
  51. /**
  52. * @type {bool}
  53. */
  54. isLoaded: false,
  55. /**
  56. * Indication if user has chosen hosts to install clients
  57. * @type {bool}
  58. */
  59. isClientsSet: false,
  60. /**
  61. * Define state for submit button
  62. * @type {bool}
  63. */
  64. submitDisabled: Em.computed.or('validationInProgress', 'App.router.btnClickInProgress'),
  65. /**
  66. * timer for validation request
  67. */
  68. timer: null,
  69. /**
  70. * true if request for validation is in progress
  71. *
  72. * @type {bool}
  73. */
  74. validationInProgress: false,
  75. /**
  76. * Check if <code>addHostWizard</code> used
  77. * @type {bool}
  78. */
  79. isAddHostWizard: Em.computed.equal('content.controllerName', 'addHostController'),
  80. /**
  81. * Check if <code>installerWizard</code> used
  82. * @type {bool}
  83. */
  84. isInstallerWizard: Em.computed.equal('content.controllerName', 'installerController'),
  85. isAllCheckboxesEmpty: function() {
  86. var hosts = this.get('hosts');
  87. for (var i = 0; i < hosts.length; i++) {
  88. var checkboxes = hosts[i].checkboxes;
  89. for (var j = 0; j < checkboxes.length; j++) {
  90. if (checkboxes[j].checked) {
  91. return false;
  92. }
  93. }
  94. }
  95. return true;
  96. },
  97. /**
  98. * Check if <code>addServiceWizard</code> used
  99. * @type {bool}
  100. */
  101. isAddServiceWizard: Em.computed.equal('content.controllerName', 'addServiceController'),
  102. installedServiceNames: function () {
  103. return this.get('content.services').filterProperty('isInstalled').mapProperty('serviceName');
  104. }.property('content.services').cacheable(),
  105. /**
  106. * Validation error messages which don't related with any master
  107. */
  108. generalErrorMessages: [],
  109. /**
  110. * Validation warning messages which don't related with any master
  111. */
  112. generalWarningMessages: [],
  113. /**
  114. * true if validation has any general (which is not related with concrete host) error message
  115. */
  116. anyGeneralErrors: Em.computed.or('errorMessage','generalErrorMessages.length'),
  117. /**
  118. * true if validation has any general (which is not related with concrete host) warning message
  119. */
  120. anyGeneralWarnings: Em.computed.gt('generalWarningMessages.length', 0),
  121. /**
  122. * true if validation has any general (which is not related with concrete host) error or warning message
  123. */
  124. anyGeneralIssues: Em.computed.or('anyGeneralErrors', 'anyGeneralWarnings'),
  125. anyHostErrors: function () {
  126. return this.get('hosts').some(function(h) { return h.errorMessages ? h.errorMessages.length > 0 : false;});
  127. }.property('hosts.@each.errorMessages'),
  128. /**
  129. * true if validation has any error message (general or host specific)
  130. */
  131. anyErrors: Em.computed.or('anyGeneralErrors', 'anyHostErrors'),
  132. anyHostWarnings: function () {
  133. return this.get('hosts').some(function(h) { return h.warnMessages ? h.warnMessages.length > 0 : false;});
  134. }.property('hosts.@each.warnMessages'),
  135. /**
  136. * true if validation has any warning message (general or host specific)
  137. */
  138. anyWarnings: Em.computed.or('anyGeneralWarnings', 'anyHostWarnings'),
  139. openSlavesAndClientsIssues: function () {
  140. App.ModalPopup.show({
  141. header: Em.I18n.t('installer.step6.validationSlavesAndClients.popup.header'),
  142. bodyClass: Em.View.extend({
  143. controller: this,
  144. templateName: require('templates/wizard/step6/step6_issues_popup')
  145. }),
  146. secondary: null
  147. });
  148. },
  149. /**
  150. * Verify condition that at least one checkbox of each component was checked
  151. * @method clearError
  152. */
  153. clearError: function () {
  154. var self = this;
  155. var isError = false;
  156. var err = false;
  157. var hosts = this.get('hosts');
  158. var headers = this.get('headers');
  159. var headersMap = headers.toWickMapByProperty('name');
  160. hosts.forEach(function (host) {
  161. host.checkboxes.forEach(function (checkbox) {
  162. if (headersMap[checkbox.component]) {
  163. headersMap[checkbox.component] = !checkbox.checked;
  164. }
  165. });
  166. });
  167. for (var i in headersMap) {
  168. err |= headersMap[i];
  169. }
  170. if (!err) {
  171. this.set('errorMessage', '');
  172. }
  173. if (this.get('isAddHostWizard')) {
  174. hosts.forEach(function (host) {
  175. isError = false;
  176. headers.forEach(function (header) {
  177. isError |= host.checkboxes.findProperty('title', header.get('label')).checked;
  178. });
  179. isError = !isError;
  180. if (!isError) {
  181. self.set('errorMessage', '');
  182. }
  183. });
  184. }
  185. },
  186. /**
  187. * Clear Step6 data like <code>hosts</code>, <code>headers</code> etc
  188. * @method clearStep
  189. */
  190. clearStep: function () {
  191. this.set('hosts', []);
  192. this.set('headers', []);
  193. this.clearError();
  194. this.set('isLoaded', false);
  195. },
  196. /**
  197. * Enable some service for all hosts
  198. * @param {object} event
  199. * @method selectAllNodes
  200. */
  201. selectAllNodes: function (event) {
  202. var name = Em.get(event, 'context.name');
  203. if (name) {
  204. this.setAllNodes(name, true);
  205. this.callValidation();
  206. }
  207. },
  208. /**
  209. * Disable some services for all hosts
  210. * @param {object} event
  211. * @method deselectAllNodes
  212. */
  213. deselectAllNodes: function (event) {
  214. var name = Em.get(event, 'context.name');
  215. if (name) {
  216. this.setAllNodes(name, false);
  217. this.callValidation();
  218. }
  219. },
  220. /**
  221. * Enable/disable some service for all hosts
  222. * @param {String} component - component name
  223. * @param {bool} checked - true - enable, false - disable
  224. * @method setAllNodes
  225. */
  226. setAllNodes: function (component, checked) {
  227. this.get('hosts').forEach(function (host) {
  228. host.checkboxes.filterProperty('isInstalled', false).forEach(function (checkbox) {
  229. if (checkbox.component === component) {
  230. Em.set(checkbox, 'checked', checked);
  231. }
  232. });
  233. });
  234. this.checkCallback(component);
  235. },
  236. /**
  237. * Checkbox check callback
  238. * Verify if all/none checkboxes for current component are checked
  239. * @param {String} component
  240. * @method checkCallback
  241. */
  242. checkCallback: function (component) {
  243. var header = this.get('headers').findProperty('name', component);
  244. if (header) {
  245. var hosts = this.get('hosts');
  246. var allTrue = true;
  247. var allFalse = true;
  248. hosts.forEach(function (host) {
  249. host.checkboxes.forEach(function (checkbox) {
  250. if (checkbox.component === component && !checkbox.isInstalled) {
  251. allTrue = allTrue && checkbox.checked;
  252. allFalse = allFalse && !checkbox.checked;
  253. }
  254. });
  255. });
  256. header.set('allChecked', allTrue);
  257. header.set('noChecked', allFalse);
  258. }
  259. this.clearError();
  260. },
  261. /**
  262. * Init step6 data
  263. * @method loadStep
  264. */
  265. loadStep: function () {
  266. this.clearStep();
  267. var selectedServices = App.StackService.find().filterProperty('isSelected');
  268. var installedServices = App.StackService.find().filterProperty('isInstalled');
  269. var services;
  270. if (this.get('isInstallerWizard')) services = selectedServices;
  271. else if (this.get('isAddHostWizard')) services = installedServices;
  272. else if (this.get('isAddServiceWizard')) services = installedServices.concat(selectedServices);
  273. var headers = Em.A([]);
  274. services.forEach(function (stackService) {
  275. stackService.get('serviceComponents').forEach(function (serviceComponent) {
  276. if (serviceComponent.get('isShownOnInstallerSlaveClientPage')) {
  277. headers.pushObject(Em.Object.create({
  278. name: serviceComponent.get('componentName'),
  279. label: App.format.role(serviceComponent.get('componentName'), false),
  280. allChecked: false,
  281. isRequired: serviceComponent.get('isRequired'),
  282. noChecked: true,
  283. isDisabled: installedServices.someProperty('serviceName', stackService.get('serviceName')) && this.get('isAddServiceWizard'),
  284. allId: 'all-' + serviceComponent.get('componentName'),
  285. noneId: 'none-' + serviceComponent.get('componentName')
  286. }));
  287. }
  288. }, this);
  289. }, this);
  290. if (this.get('content.clients') && !!this.get('content.clients').length) {
  291. headers.pushObject(Em.Object.create({
  292. name: 'CLIENT',
  293. label: App.format.role('CLIENT', false),
  294. allChecked: false,
  295. noChecked: true,
  296. isDisabled: false,
  297. allId: 'all-CLIENT',
  298. noneId: 'none-CLIENT'
  299. }));
  300. }
  301. this.get('headers').pushObjects(headers);
  302. this.render();
  303. if (this.get('content.skipSlavesStep')) {
  304. App.router.send('next');
  305. } else {
  306. this.callValidation();
  307. }
  308. },
  309. /**
  310. * Get active host names
  311. * @return {string[]}
  312. * @method getHostNames
  313. */
  314. getHostNames: function () {
  315. var hostInfo = this.get('content.hosts');
  316. var hostNames = [];
  317. //flag identify whether get all hosts or only uninstalled(newly added) hosts
  318. var getUninstalledHosts = this.get('content.controllerName') !== 'addServiceController';
  319. for (var index in hostInfo) {
  320. if (hostInfo.hasOwnProperty(index)) {
  321. if (hostInfo[index].bootStatus === 'REGISTERED') {
  322. if (!getUninstalledHosts || !hostInfo[index].isInstalled) {
  323. hostNames.push(hostInfo[index].name);
  324. }
  325. }
  326. }
  327. }
  328. return hostNames;
  329. },
  330. /**
  331. * Load all data needed for this module. Then it automatically renders in template
  332. * @method render
  333. */
  334. render: function () {
  335. var hostsObj = [],
  336. masterHosts = [],
  337. headers = this.get('headers'),
  338. masterHostNames = this.get('content.masterComponentHosts').mapProperty('hostName').uniq(),
  339. masterHostNamesMap = masterHostNames.toWickMap();
  340. this.getHostNames().forEach(function (_hostName) {
  341. var hasMaster = masterHostNamesMap[_hostName];
  342. var obj = {
  343. hostName: _hostName,
  344. hasMaster: hasMaster,
  345. checkboxes: headers.map(function (header) {
  346. return{
  347. component: header.name,
  348. title: header.label,
  349. checked: false,
  350. isInstalled: false,
  351. isDisabled: header.get('isDisabled')
  352. };
  353. })
  354. };
  355. if (hasMaster) {
  356. masterHosts.pushObject(obj)
  357. } else {
  358. hostsObj.pushObject(obj);
  359. }
  360. });
  361. //hosts with master components should be in the beginning of list
  362. hostsObj.unshift.apply(hostsObj, masterHosts);
  363. hostsObj = this.renderSlaves(hostsObj);
  364. this.set('hosts', hostsObj);
  365. headers.forEach(function (header) {
  366. this.checkCallback(header.get('name'));
  367. }, this);
  368. this.set('isLoaded', true);
  369. },
  370. /**
  371. * Set checked values for slaves checkboxes
  372. * @param {Array} hostsObj
  373. * @return {Array}
  374. * @method renderSlaves
  375. */
  376. renderSlaves: function (hostsObj) {
  377. var slaveComponents = this.get('content.slaveComponentHosts');
  378. if (Em.isNone(slaveComponents)) { // we are at this page for the first time
  379. this.selectRecommendedComponents(hostsObj);
  380. this.setInstalledComponents(hostsObj);
  381. } else {
  382. this.restoreComponentsSelection(hostsObj, slaveComponents);
  383. }
  384. this.selectClientHost(hostsObj);
  385. return hostsObj;
  386. },
  387. /**
  388. * set installed flag of host-components
  389. * @param {Array} hostsObj
  390. * @returns {boolean}
  391. */
  392. setInstalledComponents: function(hostsObj) {
  393. if (Em.isNone(this.get('content.installedHosts'))) return false;
  394. var hosts = this.get('content.installedHosts');
  395. hostsObj.forEach(function(host) {
  396. var installedHost = hosts[host.hostName];
  397. var installedComponents = installedHost ? installedHost.hostComponents.mapProperty('HostRoles.component_name') : [];
  398. host.checkboxes.forEach(function(checkbox) {
  399. checkbox.isInstalled = installedComponents.contains(checkbox.component);
  400. });
  401. });
  402. },
  403. /**
  404. * restore previous component selection
  405. * @param {Array} hostsObj
  406. * @param {Array} slaveComponents
  407. */
  408. restoreComponentsSelection: function(hostsObj, slaveComponents) {
  409. var slaveComponentsMap = slaveComponents.toMapByProperty('componentName');
  410. var hostsObjMap = hostsObj.toMapByProperty('hostName');
  411. this.get('headers').forEach(function (header) {
  412. var slaveComponent = slaveComponentsMap[header.get('name')];
  413. if (slaveComponent) {
  414. slaveComponent.hosts.forEach(function (_node) {
  415. var node = hostsObjMap[_node.hostName];
  416. if (node) {
  417. Em.set(node.checkboxes.findProperty('title', header.get('label')), 'checked', true);
  418. Em.set(node.checkboxes.findProperty('title', header.get('label')), 'isInstalled', _node.isInstalled);
  419. }
  420. });
  421. }
  422. });
  423. },
  424. /**
  425. * select component which should be checked according to recommendations
  426. * @param hostsObj
  427. */
  428. selectRecommendedComponents: function(hostsObj) {
  429. var recommendations = this.get('content.recommendations'),
  430. recommendedMap = {},
  431. clientComponentsMap = App.get('components.clients').toWickMap();
  432. recommendations.blueprint.host_groups.forEach(function(hostGroup) {
  433. var group = recommendations.blueprint_cluster_binding.host_groups.findProperty('name', hostGroup.name);
  434. var hosts = group.hosts || [];
  435. hosts.forEach(function (host) {
  436. recommendedMap[host.fqdn] = hostGroup.components.mapProperty('name');
  437. });
  438. });
  439. hostsObj.forEach(function (host) {
  440. var checkboxes = host.checkboxes;
  441. var hostComponents = recommendedMap[host.hostName] || [];
  442. checkboxes.forEach(function (checkbox) {
  443. var checked = hostComponents.contains(checkbox.component);
  444. if (checkbox.component === 'CLIENT' && !checked) {
  445. checked = hostComponents.some(function(componentName) {
  446. return clientComponentsMap[componentName];
  447. });
  448. }
  449. checkbox.checked = checked;
  450. });
  451. });
  452. },
  453. /**
  454. * For clients - select first non-master host, if all has masters then last host
  455. * @param hostsObj
  456. */
  457. selectClientHost: function (hostsObj) {
  458. if (!this.get('isClientsSet')) {
  459. var nonMasterHost = hostsObj.findProperty('hasMaster', false);
  460. var clientHost = !!nonMasterHost ? nonMasterHost : hostsObj[hostsObj.length - 1]; // last host
  461. var clientCheckBox = clientHost.checkboxes.findProperty('component', 'CLIENT');
  462. if (clientCheckBox) {
  463. Em.set(clientCheckBox, 'checked', true);
  464. }
  465. this.set('isClientsSet', true);
  466. }
  467. },
  468. /**
  469. * Select checkboxes which correspond to master components
  470. *
  471. * @param {Array} hostsObj
  472. * @return {Array}
  473. * @method selectMasterComponents
  474. */
  475. selectMasterComponents: function (hostsObj) {
  476. var masterComponentHosts = this.get('content.masterComponentHosts');
  477. if (masterComponentHosts) {
  478. masterComponentHosts.forEach(function (item) {
  479. var host = hostsObj.findProperty('hostName', item.hostName);
  480. if (host) {
  481. var checkbox = host.get('checkboxes').findProperty('component', item.component);
  482. if (checkbox) {
  483. checkbox.set('checked', true);
  484. }
  485. }
  486. });
  487. }
  488. return hostsObj;
  489. },
  490. /**
  491. * Return list of master components for specified <code>hostname</code>
  492. * @param {string} hostName
  493. * @return {string[]}
  494. * @method getMasterComponentsForHost
  495. */
  496. getMasterComponentsForHost: function (hostName) {
  497. return this.get('content.masterComponentHosts').filterProperty('hostName', hostName).mapProperty('component');
  498. },
  499. callValidation: function (successCallback) {
  500. var self = this;
  501. clearTimeout(this.get('timer'));
  502. if (this.get('validationInProgress')) {
  503. this.set('timer', setTimeout(function () {
  504. self.callValidation(successCallback);
  505. }, 700));
  506. } else {
  507. this.callServerSideValidation(successCallback);
  508. }
  509. },
  510. /**
  511. * Update submit button status
  512. * @method callServerSideValidation
  513. */
  514. callServerSideValidation: function (successCallback) {
  515. var self = this;
  516. this.set('validationInProgress', true);
  517. var selectedServices = App.StackService.find().filterProperty('isSelected').mapProperty('serviceName');
  518. var installedServices = App.StackService.find().filterProperty('isInstalled').mapProperty('serviceName');
  519. var services = installedServices.concat(selectedServices).uniq();
  520. var hostNames = self.get('hosts').mapProperty('hostName');
  521. var slaveBlueprint = self.getCurrentBlueprint();
  522. var masterBlueprint = null;
  523. //Existing Installed but invisible masters on `Assign Masters page` should be included in host component layout for recommnedation/validation call
  524. var invisibleInstalledMasters = [];
  525. if (this.get('isAddServiceWizard')) {
  526. var invisibleMasters = App.StackServiceComponent.find().filterProperty("isMaster").filterProperty("isShownOnAddServiceAssignMasterPage", false);
  527. invisibleInstalledMasters = invisibleMasters.filter(function(item){
  528. var masterComponent = App.MasterComponent.find().findProperty('componentName', item.get('componentName'));
  529. return masterComponent && !!masterComponent.get('totalCount');
  530. }).mapProperty("componentName");
  531. }
  532. var invisibleSlavesAndClients = App.StackServiceComponent.find().filter(function (component) {
  533. return component.get("isSlave") && component.get("isShownOnInstallerSlaveClientPage") === false ||
  534. component.get("isClient") && component.get("isRequiredOnAllHosts");
  535. }).mapProperty("componentName");
  536. if (this.get('isInstallerWizard') || this.get('isAddServiceWizard')) {
  537. masterBlueprint = self.getCurrentMastersBlueprint();
  538. var selectedClientComponents = self.get('content.clients').mapProperty('component_name');
  539. var alreadyInstalledClients = App.get('components.clients').reject(function (c) {
  540. return selectedClientComponents.contains(c);
  541. });
  542. var invisibleComponents = invisibleInstalledMasters.concat(invisibleSlavesAndClients).concat(alreadyInstalledClients);
  543. var invisibleBlueprint = blueprintUtils.filterByComponents(this.get('content.recommendations'), invisibleComponents);
  544. masterBlueprint = blueprintUtils.mergeBlueprints(masterBlueprint, invisibleBlueprint);
  545. } else if (this.get('isAddHostWizard')) {
  546. masterBlueprint = self.getCurrentMasterSlaveBlueprint();
  547. hostNames = hostNames.concat(App.Host.find().mapProperty("hostName")).uniq();
  548. slaveBlueprint = blueprintUtils.addComponentsToBlueprint(slaveBlueprint, invisibleSlavesAndClients);
  549. }
  550. var bluePrintsForValidation = blueprintUtils.mergeBlueprints(masterBlueprint, slaveBlueprint);
  551. this.set('content.recommendationsHostGroups', bluePrintsForValidation);
  552. return App.ajax.send({
  553. name: 'config.validations',
  554. sender: self,
  555. data: {
  556. stackVersionUrl: App.get('stackVersionURL'),
  557. hosts: hostNames,
  558. services: services,
  559. validate: 'host_groups',
  560. recommendations: bluePrintsForValidation
  561. },
  562. success: 'updateValidationsSuccessCallback',
  563. error: 'updateValidationsErrorCallback'
  564. }).
  565. then(function () {
  566. self.set('validationInProgress', false);
  567. if (App.get('router.btnClickInProgress') && successCallback) {
  568. successCallback();
  569. }
  570. }
  571. );
  572. },
  573. /**
  574. * Success-callback for validations request
  575. * @param {object} data
  576. * @method updateValidationsSuccessCallback
  577. */
  578. updateValidationsSuccessCallback: function (data) {
  579. var self = this;
  580. var clientComponents = App.get('components.clients');
  581. this.set('generalErrorMessages', []);
  582. this.set('generalWarningMessages', []);
  583. this.get('hosts').setEach('warnMessages', []);
  584. this.get('hosts').setEach('errorMessages', []);
  585. this.get('hosts').setEach('anyMessage', false);
  586. this.get('hosts').forEach(function (host) {
  587. host.checkboxes.setEach('hasWarnMessage', false);
  588. host.checkboxes.setEach('hasErrorMessage', false);
  589. });
  590. var anyGeneralClientErrors = false; // any error/warning for any client component (under "CLIENT" alias)
  591. var validationData = validationUtils.filterNotInstalledComponents(data);
  592. validationData.filterProperty('type', 'host-component').filter(function (i) {
  593. return !(i['component-name'] && App.StackServiceComponent.find().findProperty('componentName', i['component-name']).get('isMaster'));
  594. }).forEach(function (item) {
  595. var checkboxWithIssue = null;
  596. var isGeneralClientValidationItem = clientComponents.contains(item['component-name']); // it is an error/warning for any client component (under "CLIENT" alias)
  597. var host = self.get('hosts').find(function (h) {
  598. return h.hostName === item.host && h.checkboxes.some(function (checkbox) {
  599. var isClientComponent = checkbox.component === "CLIENT" && isGeneralClientValidationItem;
  600. if (checkbox.component === item['component-name'] || isClientComponent) {
  601. checkboxWithIssue = checkbox;
  602. return true;
  603. }
  604. return false;
  605. });
  606. });
  607. if (host) {
  608. Em.set(host, 'anyMessage', true);
  609. if (item.level === 'ERROR') {
  610. host.errorMessages.pushObject(item.message);
  611. Em.set(checkboxWithIssue, 'hasErrorMessage', true);
  612. }
  613. else
  614. if (item.level === 'WARN') {
  615. host.warnMessages.pushObject(item.message);
  616. Em.set(checkboxWithIssue, 'hasWarnMessage', true);
  617. }
  618. }
  619. else {
  620. var component;
  621. if (isGeneralClientValidationItem) {
  622. if (!anyGeneralClientErrors) {
  623. anyGeneralClientErrors = true;
  624. component = "Client";
  625. }
  626. }
  627. else {
  628. component = item['component-name'];
  629. }
  630. if (component || !item['component-name']) {
  631. var details = "";
  632. if (item.host) {
  633. details += " (" + item.host + ")";
  634. }
  635. if (item.level === 'ERROR') {
  636. self.get('generalErrorMessages').push(item.message + details);
  637. }
  638. else
  639. if (item.level === 'WARN') {
  640. self.get('generalWarningMessages').push(item.message + details);
  641. }
  642. }
  643. }
  644. });
  645. },
  646. /**
  647. * Error-callback for validations request
  648. * @param {object} jqXHR
  649. * @param {object} ajaxOptions
  650. * @param {string} error
  651. * @param {object} opt
  652. * @method updateValidationsErrorCallback
  653. */
  654. updateValidationsErrorCallback: function (jqXHR, ajaxOptions, error, opt) {
  655. },
  656. /**
  657. * Composes selected values of comboboxes into blueprint format
  658. */
  659. getCurrentBlueprint: function () {
  660. var self = this;
  661. var res = {
  662. blueprint: { host_groups: [] },
  663. blueprint_cluster_binding: { host_groups: [] }
  664. };
  665. var clientComponents = self.get('content.clients').mapProperty('component_name');
  666. var mapping = self.get('hosts');
  667. mapping.forEach(function (item, i) {
  668. var groupName = 'host-group-' + (i+1);
  669. var hostGroup = {
  670. name: groupName,
  671. components: item.checkboxes.filterProperty('checked', true).map(function (checkbox) {
  672. if (checkbox.component === "CLIENT") {
  673. return clientComponents.map(function (client) {
  674. return { name: client };
  675. });
  676. } else {
  677. return { name: checkbox.component };
  678. }
  679. })
  680. };
  681. hostGroup.components = [].concat.apply([], hostGroup.components);
  682. var binding = {
  683. name: groupName,
  684. hosts: [
  685. { fqdn: item.hostName }
  686. ]
  687. };
  688. res.blueprint.host_groups.push(hostGroup);
  689. res.blueprint_cluster_binding.host_groups.push(binding);
  690. });
  691. return res;
  692. },
  693. /**
  694. * Create blueprint from assigned master components to appropriate hosts
  695. * @returns {Object}
  696. * @method getCurrentMastersBlueprint
  697. */
  698. getCurrentMastersBlueprint: function () {
  699. var res = {
  700. blueprint: { host_groups: [] },
  701. blueprint_cluster_binding: { host_groups: [] }
  702. };
  703. var masters = this.get('content.masterComponentHosts');
  704. var hosts = this.get('content.hosts');
  705. Em.keys(hosts).forEach(function (host, i) {
  706. var groupName = 'host-group-' + (i + 1);
  707. var components = [];
  708. masters.forEach(function (master) {
  709. if (master.hostName === host) {
  710. components.push({
  711. name: master.component
  712. });
  713. }
  714. });
  715. res.blueprint.host_groups.push({
  716. name: groupName,
  717. components: components
  718. });
  719. res.blueprint_cluster_binding.host_groups.push({
  720. name: groupName,
  721. hosts: [
  722. {
  723. fqdn: host
  724. }
  725. ]
  726. });
  727. }, this);
  728. return blueprintUtils.mergeBlueprints(res, this.getCurrentSlaveBlueprint());
  729. },
  730. /**
  731. * In case of any validation issues shows accept dialog box for user which allow cancel and fix issues or continue anyway
  732. * @metohd submit
  733. */
  734. showValidationIssuesAcceptBox: function(callback) {
  735. var self = this;
  736. if (self.get('anyWarnings') || self.get('anyErrors')) {
  737. App.ModalPopup.show({
  738. primary: Em.I18n.t('common.continueAnyway'),
  739. header: Em.I18n.t('installer.step6.validationIssuesAttention.header'),
  740. body: Em.I18n.t('installer.step6.validationIssuesAttention'),
  741. primaryClass: 'btn-danger',
  742. onPrimary: function () {
  743. this.hide();
  744. callback();
  745. },
  746. onSecondary: function () {
  747. App.set('router.nextBtnClickInProgress', false);
  748. this._super();
  749. }
  750. });
  751. } else {
  752. callback();
  753. }
  754. }
  755. });