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