step6_controller.js 15 KB

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