step6_controller.js 27 KB

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