step6_controller.js 26 KB

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