step6_controller.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  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. /**
  21. * By Step 6, we have the following information stored in App.db and set on this
  22. * controller by the router:
  23. *
  24. * hosts: App.db.hosts (list of all hosts the user selected in Step 3)
  25. * selectedServiceNames: App.db.selectedServiceNames (the services that the user selected in Step 4)
  26. * masterComponentHosts: App.db.masterComponentHosts (master-components-to-hosts mapping the user selected in Step 5)
  27. *
  28. * Step 6 will set the following information in App.db:
  29. * slaveComponentHosts: App.db.slaveComponentHosts (slave-components-to-hosts mapping the user selected in Step 6)
  30. *
  31. */
  32. App.WizardStep6Controller = Em.Controller.extend({
  33. /**
  34. * List of hosts
  35. * @type {object[]}
  36. */
  37. hosts: [],
  38. /**
  39. * List of components info about selecting/deselecting status for components.
  40. *
  41. * @type {Array}
  42. * @item {Em.Object}
  43. * @property name {String} - component name
  44. * @property label {String} - component display name
  45. * @property allChecked {bool} - all checkboxes are checked
  46. * @property noChecked {bool} - no checkboxes checked
  47. */
  48. headers: [],
  49. /**
  50. * true - assign ZK, HB
  51. * false - slaves and clients
  52. * @type {bool}
  53. */
  54. isMasters: false,
  55. /**
  56. * @type {bool}
  57. */
  58. isLoaded: false,
  59. /**
  60. * Check if <code>addHostWizard</code> used
  61. * @type {bool}
  62. */
  63. isAddHostWizard: function () {
  64. return this.get('content.controllerName') === 'addHostController';
  65. }.property('content.controllerName'),
  66. /**
  67. * Check if <code>installerWizard</code> used
  68. * @type {bool}
  69. */
  70. isInstallerWizard: function () {
  71. return this.get('content.controllerName') === 'installerController';
  72. }.property('content.controllerName'),
  73. /**
  74. * Check if <code>addHerviceWizard</code> used
  75. * @type {bool}
  76. */
  77. isAddServiceWizard: function () {
  78. return this.get('content.controllerName') === 'addServiceController';
  79. }.property('content.controllerName'),
  80. /**
  81. * Verify condition that at least one checkbox of each component was checked
  82. * @method clearError
  83. */
  84. clearError: function () {
  85. var self = this;
  86. var isError = false;
  87. var err = false;
  88. var hosts = this.get('hosts');
  89. var headers = this.get('headers');
  90. var headersMap = {};
  91. headers.forEach(function (header) {
  92. headersMap[header.name] = true;
  93. });
  94. hosts.forEach(function (host) {
  95. host.get('checkboxes').forEach(function (checkbox) {
  96. if (headersMap[checkbox.get('component')]) {
  97. headersMap[checkbox.get('component')] = !checkbox.get('checked');
  98. }
  99. });
  100. });
  101. for (var i in headersMap) {
  102. err |= headersMap[i];
  103. }
  104. if (!err) {
  105. this.set('errorMessage', '');
  106. }
  107. if (this.get('isAddHostWizard')) {
  108. if (this.get('isMasters')) {
  109. this.set('errorMessage', '');
  110. }
  111. else {
  112. hosts.forEach(function (host) {
  113. isError = false;
  114. headers.forEach(function (header) {
  115. isError |= host.get('checkboxes').findProperty('title', header.get('label')).checked;
  116. });
  117. isError = !isError;
  118. if (!isError) {
  119. self.set('errorMessage', '');
  120. }
  121. });
  122. }
  123. }
  124. },
  125. /**
  126. * Clear Step6 data like <code>hosts</code>, <code>headers</code> etc
  127. * @method clearStep
  128. */
  129. clearStep: function () {
  130. this.set('hosts', []);
  131. this.set('headers', []);
  132. this.clearError();
  133. this.set('isLoaded', false);
  134. },
  135. /**
  136. * Enable some service for all hosts
  137. * @param {object} event
  138. * @method selectAllNodes
  139. */
  140. selectAllNodes: function (event) {
  141. var name = Em.get(event, 'context.name');
  142. if (name) {
  143. this.setAllNodes(name, true);
  144. }
  145. },
  146. /**
  147. * Disable some services for all hosts
  148. * @param {object} event
  149. * @method deselectAllNodes
  150. */
  151. deselectAllNodes: function (event) {
  152. var name = Em.get(event, 'context.name');
  153. if (name) {
  154. this.setAllNodes(name, false);
  155. }
  156. },
  157. /**
  158. * Enable/disable some service for all hosts
  159. * @param {String} component - component name
  160. * @param {bool} checked - true - enable, false - disable
  161. * @method setAllNodes
  162. */
  163. setAllNodes: function (component, checked) {
  164. this.get('hosts').forEach(function (host) {
  165. host.get('checkboxes').filterProperty('isInstalled', false).forEach(function (checkbox) {
  166. if (checkbox.get('component') === component) {
  167. checkbox.set('checked', checked);
  168. }
  169. });
  170. });
  171. this.checkCallback(component);
  172. },
  173. /**
  174. * Return whether service was selected or not
  175. * @param {string} name serviceName
  176. * @return {bool}
  177. * @method isServiceSelected
  178. */
  179. isServiceSelected: function (name) {
  180. return !!(this.get('content.services').findProperty('serviceName', name) &&
  181. this.get('content.services').findProperty('serviceName', name).get('isSelected'));
  182. },
  183. /**
  184. * Checkbox check callback
  185. * Verify if all/none checkboxes for current component are checked
  186. * @param {String} component
  187. * @method checkCallback
  188. */
  189. checkCallback: function (component) {
  190. var header = this.get('headers').findProperty('name', component);
  191. if (header) {
  192. var hosts = this.get('hosts');
  193. var allTrue = true;
  194. var allFalse = true;
  195. hosts.forEach(function (host) {
  196. host.get('checkboxes').forEach(function (checkbox) {
  197. if (checkbox.get('component') === component && !checkbox.get('isInstalled')) {
  198. allTrue = allTrue && checkbox.get('checked');
  199. allFalse = allFalse && !checkbox.get('checked');
  200. }
  201. });
  202. });
  203. header.set('allChecked', allTrue);
  204. header.set('noChecked', allFalse);
  205. }
  206. this.clearError();
  207. },
  208. /**
  209. * Get <code>displayName</code> for component by <code>componentName</code>
  210. * @param componentName
  211. * @returns {string}
  212. * @method getComponentDisplayName
  213. */
  214. getComponentDisplayName: function (componentName) {
  215. return App.StackServiceComponent.find().findProperty('componentName', componentName).get('displayName');
  216. },
  217. /**
  218. * Init step6 data
  219. * @method loadStep
  220. */
  221. loadStep: function () {
  222. var self = this;
  223. console.log("WizardStep6Controller: Loading step6: Assign Slaves");
  224. this.clearStep();
  225. var headers = Em.A([]);
  226. if (this.get('isMasters')) {
  227. if (this.isServiceSelected('HBASE') && App.supports.multipleHBaseMasters) {
  228. headers.pushObject(Em.Object.create({
  229. name: 'HBASE_MASTER',
  230. label: self.getComponentDisplayName('HBASE_MASTER')
  231. }));
  232. }
  233. if (this.isServiceSelected('ZOOKEEPER')) {
  234. headers.pushObject(Em.Object.create({
  235. name: 'ZOOKEEPER_SERVER',
  236. label: self.getComponentDisplayName('ZOOKEEPER_SERVER')
  237. }));
  238. }
  239. }
  240. else {
  241. if (this.isServiceSelected('HDFS')) {
  242. headers.pushObject(Em.Object.create({
  243. name: 'DATANODE',
  244. label: self.getComponentDisplayName('DATANODE')
  245. }));
  246. }
  247. if (this.isServiceSelected('MAPREDUCE')) {
  248. headers.pushObject(Em.Object.create({
  249. name: 'TASKTRACKER',
  250. label: self.getComponentDisplayName('TASKTRACKER')
  251. }));
  252. }
  253. if (this.isServiceSelected('YARN')) {
  254. headers.pushObject(Em.Object.create({
  255. name: 'NODEMANAGER',
  256. label: self.getComponentDisplayName('NODEMANAGER')
  257. }));
  258. }
  259. if (this.isServiceSelected('HBASE')) {
  260. headers.pushObject(Em.Object.create({
  261. name: 'HBASE_REGIONSERVER',
  262. label: self.getComponentDisplayName('HBASE_REGIONSERVER')
  263. }));
  264. }
  265. if (this.isServiceSelected('STORM')) {
  266. headers.pushObject(Em.Object.create({
  267. name: 'SUPERVISOR',
  268. label: self.getComponentDisplayName('SUPERVISOR')
  269. }));
  270. }
  271. if (this.isServiceSelected('FLUME')) {
  272. headers.pushObject(Em.Object.create({
  273. name: 'FLUME_HANDLER',
  274. label: self.getComponentDisplayName('FLUME_HANDLER')
  275. }));
  276. }
  277. headers.pushObject(Em.Object.create({
  278. name: 'CLIENT',
  279. label: App.format.role('CLIENT')
  280. }));
  281. }
  282. headers.forEach(function (header) {
  283. header.setProperties({ allChecked: false, noChecked: true });
  284. });
  285. this.get('headers').pushObjects(headers);
  286. this.render();
  287. if (this.get('isMasters')) {
  288. if (this.get('content.skipMasterStep')) {
  289. App.router.send('next');
  290. }
  291. }
  292. else {
  293. if (this.get('content.skipSlavesStep')) {
  294. App.router.send('next');
  295. }
  296. }
  297. },
  298. /**
  299. * Get active host names
  300. * @return {string[]}
  301. * @method getHostNames
  302. */
  303. getHostNames: function () {
  304. var hostInfo = this.get('content.hosts');
  305. var hostNames = [];
  306. for (var index in hostInfo) {
  307. if (hostInfo.hasOwnProperty(index)) {
  308. if (hostInfo[index].bootStatus === 'REGISTERED') {
  309. hostNames.push(hostInfo[index].name);
  310. }
  311. }
  312. }
  313. return hostNames;
  314. },
  315. renderHostNames: function (array) {
  316. var hostsObj = [],
  317. masterHosts = [],
  318. headers = this.get('headers'),
  319. masterHostNames = this.get('content.masterComponentHosts').mapProperty('hostName').uniq();
  320. array.forEach(function (_hostName) {
  321. var hasMaster = masterHostNames.contains(_hostName);
  322. var obj = Em.Object.create({
  323. hostName: _hostName,
  324. hasMaster: hasMaster,
  325. checkboxes: []
  326. });
  327. headers.forEach(function (header) {
  328. obj.checkboxes.pushObject(Em.Object.create({
  329. component: header.name,
  330. title: header.label,
  331. checked: false,
  332. isInstalled: false
  333. }));
  334. });
  335. if (hasMaster) {
  336. masterHosts.pushObject(obj)
  337. } else {
  338. hostsObj.pushObject(obj);
  339. }
  340. });
  341. //hosts with master components should be in the beginning of list
  342. hostsObj.unshift.apply(hostsObj, masterHosts);
  343. if (this.get('isMasters')) {
  344. hostsObj = this.selectMasterComponents(hostsObj);
  345. } else {
  346. hostsObj = this.renderSlaves(hostsObj);
  347. }
  348. this.set('hosts', hostsObj);
  349. headers.forEach(function (header) {
  350. this.checkCallback(header.get('name'));
  351. }, this);
  352. this.set('isLoaded', true);
  353. },
  354. /**
  355. * Load all data needed for this module. Then it automatically renders in template
  356. * @method render
  357. */
  358. render: function () {
  359. if (this.get('isInstallerWizard') || this.get('isAddHostWizard')) {
  360. this.renderHostNames(this.getHostNames());
  361. } else {
  362. App.ajax.send({
  363. name: 'hosts.all',
  364. sender: this,
  365. data: {
  366. clusterName: App.get('clusterName')
  367. },
  368. success: 'getHostNamesSuccessCallback'
  369. });
  370. }
  371. },
  372. getHostNamesSuccessCallback: function (response) {
  373. this.renderHostNames(response.items.mapProperty('Hosts.host_name'));
  374. },
  375. /**
  376. * Set checked values for slaves checkboxes
  377. * @param {Array} hostsObj
  378. * @return {Array}
  379. * @method renderSlaves
  380. */
  381. renderSlaves: function (hostsObj) {
  382. var self = this;
  383. var headers = this.get('headers');
  384. var slaveComponents = this.get('content.slaveComponentHosts');
  385. if (!slaveComponents) { // we are at this page for the first time
  386. var client_is_set = false;
  387. hostsObj.forEach(function (host) {
  388. var checkboxes = host.get('checkboxes');
  389. checkboxes.setEach('checked', !host.hasMaster);
  390. checkboxes.setEach('isInstalled', false);
  391. checkboxes.findProperty('title', headers.findProperty('name', 'CLIENT').get('label')).set('checked', false);
  392. // First not Master should have Client (only first!)
  393. if (!client_is_set) {
  394. if (self.isServiceSelected("HDFS")) {
  395. var checkboxDatanode = checkboxes.findProperty('title', headers.findProperty('name', 'DATANODE').get('label'));
  396. if (checkboxDatanode && checkboxDatanode.get('checked')) {
  397. checkboxes.findProperty('title', headers.findProperty('name', 'CLIENT').get('label')).set('checked', true);
  398. client_is_set = true;
  399. }
  400. }
  401. }
  402. });
  403. if (this.get('isInstallerWizard') && hostsObj.everyProperty('hasMaster', true)) {
  404. var lastHost = hostsObj[hostsObj.length - 1];
  405. lastHost.get('checkboxes').setEach('checked', true);
  406. }
  407. }
  408. else {
  409. this.get('headers').forEach(function (header) {
  410. var nodes = slaveComponents.findProperty('componentName', header.get('name'));
  411. if (nodes) {
  412. nodes.hosts.forEach(function (_node) {
  413. var node = hostsObj.findProperty('hostName', _node.hostName);
  414. if (node) {
  415. node.get('checkboxes').findProperty('title', header.get('label')).set('checked', true);
  416. node.get('checkboxes').findProperty('title', header.get('label')).set('isInstalled', _node.isInstalled);
  417. }
  418. });
  419. }
  420. });
  421. }
  422. return hostsObj;
  423. },
  424. /**
  425. * Select checkboxes which correspond to master components
  426. *
  427. * @param {Array} hostsObj
  428. * @return {Array}
  429. * @method selectMasterComponents
  430. */
  431. selectMasterComponents: function (hostsObj) {
  432. var masterComponentHosts = this.get('content.masterComponentHosts');
  433. console.log('Master components selected on:', masterComponentHosts.mapProperty('hostName').uniq().join(", "));
  434. if (masterComponentHosts) {
  435. masterComponentHosts.forEach(function (item) {
  436. var host = hostsObj.findProperty('hostName', item.hostName);
  437. if (host) {
  438. var checkbox = host.get('checkboxes').findProperty('component', item.component);
  439. if (checkbox) {
  440. checkbox.set('checked', true);
  441. }
  442. }
  443. });
  444. }
  445. return hostsObj;
  446. },
  447. /**
  448. * Return list of master components for specified <code>hostname</code>
  449. * @param {string} hostName
  450. * @return {string[]}
  451. * @method getMasterComponentsForHost
  452. */
  453. getMasterComponentsForHost: function (hostName) {
  454. return this.get('content.masterComponentHosts').filterProperty('hostName', hostName).mapProperty('component');
  455. },
  456. /**
  457. * Validate form. Return do we have errors or not
  458. * @return {bool}
  459. * @method validate
  460. */
  461. validate: function () {
  462. if (this.get('isAddHostWizard')) {
  463. return this.validateEachHost(Em.I18n.t('installer.step6.error.mustSelectOneForHost'));
  464. }
  465. else {
  466. if (this.get('isInstallerWizard')) {
  467. return this.validateEachComponent() && this.validateEachHost(Em.I18n.t('installer.step6.error.mustSelectOneForSlaveHost'));
  468. }
  469. else {
  470. if (this.get('isAddServiceWizard')) {
  471. return this.validateEachComponent();
  472. }
  473. return true;
  474. }
  475. }
  476. },
  477. /**
  478. * Validate all components for each host. Return do we have errors or not
  479. * @return {bool}
  480. * @method validateEachHost
  481. */
  482. validateEachHost: function (errorMsg) {
  483. var isError = false;
  484. var hosts = this.get('hosts');
  485. var headers = this.get('headers');
  486. for (var i = 0; i < hosts.length; i++) {
  487. if (this.get('isInstallerWizard') && this.get('content.masterComponentHosts').someProperty('hostName', hosts[i].hostName)) {
  488. continue;
  489. }
  490. var checkboxes = hosts[i].get('checkboxes');
  491. isError = false;
  492. headers.forEach(function (header) {
  493. isError = isError || checkboxes.findProperty('title', header.get('label')).checked;
  494. });
  495. isError = !isError;
  496. if (isError) {
  497. this.set('errorMessage', errorMsg);
  498. break;
  499. }
  500. }
  501. return !isError;
  502. },
  503. /**
  504. * Validate a component for all hosts. Return do we have errors or not
  505. * @return {bool}
  506. * @method validateEachComponent
  507. */
  508. validateEachComponent: function () {
  509. var isError = false;
  510. var hosts = this.get('hosts');
  511. var headers = this.get('headers');
  512. headers.forEach(function (header) {
  513. var all_false = true;
  514. hosts.forEach(function (host) {
  515. var checkboxes = host.get('checkboxes');
  516. all_false = all_false && !checkboxes.findProperty('title', header.get('label')).checked;
  517. });
  518. isError = isError || all_false;
  519. });
  520. if (isError) {
  521. this.set('errorMessage', Em.I18n.t('installer.step6.error.mustSelectOne'));
  522. }
  523. return !isError;
  524. }
  525. });