add_controller.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  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. App.AddServiceController = App.WizardController.extend(App.AddSecurityConfigs, {
  20. name: 'addServiceController',
  21. // @TODO: remove after Kerberos Automation supports
  22. totalSteps: App.supports.automatedKerberos ? 8 : 7,
  23. /**
  24. * Used for hiding back button in wizard
  25. */
  26. hideBackButton: true,
  27. /**
  28. * @type {object}
  29. * @default null
  30. */
  31. serviceToInstall: null,
  32. /**
  33. *
  34. */
  35. installClientQueueLength: 0,
  36. /**
  37. * All wizards data will be stored in this variable
  38. *
  39. * cluster - cluster name
  40. * installOptions - ssh key, repo info, etc.
  41. * services - services list
  42. * hosts - list of selected hosts
  43. * slaveComponentHosts, - info about slave hosts
  44. * masterComponentHosts - info about master hosts
  45. * config??? - to be described later
  46. */
  47. content: Em.Object.create({
  48. cluster: null,
  49. hosts: null,
  50. installOptions: null,
  51. services: null,
  52. slaveComponentHosts: null,
  53. masterComponentHosts: null,
  54. serviceConfigProperties: null,
  55. advancedServiceConfig: null,
  56. controllerName: 'addServiceController',
  57. configGroups: [],
  58. clients: [],
  59. additionalClients: [],
  60. smokeuser: "ambari-qa",
  61. group: "hadoop"
  62. }),
  63. loadMap: {
  64. '1': [
  65. {
  66. type: 'sync',
  67. callback: function () {
  68. this.loadServices();
  69. }
  70. }
  71. ],
  72. '2': [
  73. {
  74. type: 'async',
  75. callback: function () {
  76. var dfd = $.Deferred();
  77. var self = this;
  78. this.loadHosts().done(function () {
  79. self.loadMasterComponentHosts();
  80. self.load('hosts');
  81. dfd.resolve();
  82. });
  83. return dfd.promise();
  84. }
  85. }
  86. ],
  87. '3': [
  88. {
  89. type: 'async',
  90. callback: function () {
  91. var dfd = $.Deferred();
  92. var self = this;
  93. this.loadHosts().done(function () {
  94. self.loadServices();
  95. self.loadClients();
  96. self.loadSlaveComponentHosts();//depends on loadServices
  97. dfd.resolve();
  98. });
  99. return dfd.promise();
  100. }
  101. }
  102. ],
  103. '4': [
  104. {
  105. type: 'async',
  106. callback: function () {
  107. var self = this;
  108. var dfd = $.Deferred();
  109. this.loadKerberosDescriptorConfigs().done(function() {
  110. self.loadServiceConfigGroups();
  111. self.loadServiceConfigProperties();
  112. dfd.resolve();
  113. });
  114. return dfd.promise();
  115. }
  116. }
  117. ],
  118. '5': [
  119. {
  120. type: 'sync',
  121. callback: function () {
  122. this.checkSecurityStatus();
  123. this.load('cluster');
  124. this.set('content.additionalClients', []);
  125. this.set('installClientQueueLength', 0);
  126. this.set('installClietsQueue', App.ajaxQueue.create({abortOnError: false}));
  127. }
  128. }
  129. ]
  130. },
  131. setCurrentStep: function (currentStep, completed) {
  132. this._super(currentStep, completed);
  133. App.clusterStatus.setClusterStatus({
  134. wizardControllerName: this.get('name'),
  135. localdb: App.db.data
  136. });
  137. },
  138. loadHosts: function () {
  139. var dfd;
  140. if (this.getDBProperty('hosts')) {
  141. dfd = $.Deferred();
  142. dfd.resolve();
  143. } else {
  144. dfd = App.ajax.send({
  145. name: 'hosts.confirmed',
  146. sender: this,
  147. data: {},
  148. success: 'loadHostsSuccessCallback',
  149. error: 'loadHostsErrorCallback'
  150. });
  151. }
  152. return dfd.promise();
  153. },
  154. loadHostsSuccessCallback: function (response) {
  155. var installedHosts = {};
  156. response.items.forEach(function (item, indx) {
  157. installedHosts[item.Hosts.host_name] = {
  158. name: item.Hosts.host_name,
  159. cpu: item.Hosts.cpu_count,
  160. memory: item.Hosts.total_mem,
  161. disk_info: item.Hosts.disk_info,
  162. osType: item.Hosts.os_type,
  163. osArch: item.Hosts.os_arch,
  164. ip: item.Hosts.ip,
  165. bootStatus: "REGISTERED",
  166. isInstalled: true,
  167. hostComponents: item.host_components,
  168. id: indx++
  169. };
  170. });
  171. this.setDBProperty('hosts', installedHosts);
  172. this.set('content.hosts', installedHosts);
  173. },
  174. loadHostsErrorCallback: function (jqXHR, ajaxOptions, error, opt) {
  175. App.ajax.defaultErrorHandler(jqXHR, opt.url, opt.method, jqXHR.status);
  176. console.log('Loading hosts failed');
  177. },
  178. /**
  179. * Load services data. Will be used at <code>Select services(step4)</code> step
  180. */
  181. loadServices: function () {
  182. var services = this.getDBProperty('services');
  183. if (!services) {
  184. services = {
  185. selectedServices: [],
  186. installedServices: []
  187. };
  188. App.StackService.find().forEach(function (item) {
  189. var isInstalled = App.Service.find().someProperty('id', item.get('serviceName'));
  190. var isSelected = item.get('serviceName') == this.get('serviceToInstall');
  191. item.set('isSelected', isInstalled || isSelected);
  192. item.set('isInstalled', isInstalled);
  193. if (isInstalled) {
  194. services.selectedServices.push(item.get('serviceName'));
  195. services.installedServices.push(item.get('serviceName'));
  196. } else if(isSelected) {
  197. services.selectedServices.push(item.get('serviceName'));
  198. }
  199. }, this);
  200. this.setDBProperty('services', services);
  201. } else {
  202. App.StackService.find().forEach(function (item) {
  203. var isSelected = services.selectedServices.contains(item.get('serviceName')) || item.get('serviceName') == this.get('serviceToInstall');
  204. var isInstalled = services.installedServices.contains(item.get('serviceName'));
  205. item.set('isSelected', isSelected || (this.get("currentStep") == "1" ? isInstalled : isSelected));
  206. item.set('isInstalled', isInstalled);
  207. }, this);
  208. var isServiceWithSlave = App.StackService.find().filterProperty('isSelected').filterProperty('hasSlave').filterProperty('isInstalled', false).length;
  209. var isServiceWithClient = App.StackService.find().filterProperty('isSelected').filterProperty('hasClient').filterProperty('isInstalled', false).length;
  210. var isServiceWithCustomAssignedNonMasters = App.StackService.find().filterProperty('isSelected').filterProperty('hasNonMastersWithCustomAssignment').filterProperty('isInstalled', false).length;
  211. this.set('content.skipSlavesStep', !isServiceWithSlave && !isServiceWithClient || !isServiceWithCustomAssignedNonMasters);
  212. if (this.get('content.skipSlavesStep')) {
  213. this.get('isStepDisabled').findProperty('step', 3).set('value', this.get('content.skipSlavesStep'));
  214. }
  215. }
  216. this.set('content.services', App.StackService.find());
  217. },
  218. /**
  219. * Save data to model
  220. * @param stepController App.WizardStep4Controller
  221. */
  222. saveServices: function (stepController) {
  223. var services = {
  224. selectedServices: [],
  225. installedServices: []
  226. };
  227. var selectedServices = stepController.get('content').filterProperty('isSelected', true).filterProperty('isInstalled', false).mapProperty('serviceName');
  228. services.selectedServices.pushObjects(selectedServices);
  229. services.installedServices.pushObjects(stepController.get('content').filterProperty('isInstalled', true).mapProperty('serviceName'));
  230. // save services that already installed but ignored on choose services page
  231. // these services marked by `isInstallable` flag with value `false`, for example `Kerberos` service
  232. services.installedServices.pushObjects(App.Service.find().mapProperty('serviceName').filter(function(serviceName) {
  233. return !services.installedServices.contains(serviceName);
  234. }));
  235. this.setDBProperty('services', services);
  236. console.log('AddServiceController.saveServices: saved data', stepController.get('content'));
  237. this.set('content.selectedServiceNames', selectedServices);
  238. this.setDBProperty('selectedServiceNames', selectedServices);
  239. var isServiceWithSlave = stepController.get('content').filterProperty('isSelected').filterProperty('hasSlave').filterProperty('isInstalled', false).mapProperty('serviceName').length;
  240. var isServiceWithClient = App.StackService.find().filterProperty('isSelected').filterProperty('hasClient').filterProperty('isInstalled', false).mapProperty('serviceName').length;
  241. this.set('content.skipSlavesStep', !isServiceWithSlave && !isServiceWithClient);
  242. if (this.get('content.skipSlavesStep')) {
  243. this.get('isStepDisabled').findProperty('step', 3).set('value', this.get('content.skipSlavesStep'));
  244. }
  245. },
  246. /**
  247. * Save Master Component Hosts data to Main Controller
  248. * @param stepController App.WizardStep5Controller
  249. */
  250. saveMasterComponentHosts: function (stepController) {
  251. var obj = stepController.get('selectedServicesMasters');
  252. var masterComponentHosts = [];
  253. var installedComponents = App.HostComponent.find();
  254. obj.forEach(function (_component) {
  255. var installedComponent = installedComponents.findProperty('componentName', _component.component_name);
  256. masterComponentHosts.push({
  257. display_name: _component.display_name,
  258. component: _component.component_name,
  259. hostName: _component.selectedHost,
  260. serviceId: _component.serviceId,
  261. isInstalled: !!installedComponent,
  262. workStatus: installedComponent && installedComponent.get('workStatus')
  263. });
  264. });
  265. console.log("AddServiceController.saveMasterComponentHosts: saved hosts ", masterComponentHosts);
  266. this.setDBProperty('masterComponentHosts', masterComponentHosts);
  267. this.set('content.masterComponentHosts', masterComponentHosts);
  268. this.set('content.skipMasterStep', this.get('content.masterComponentHosts').everyProperty('isInstalled', true));
  269. this.get('isStepDisabled').findProperty('step', 2).set('value', this.get('content.skipMasterStep'));
  270. },
  271. /**
  272. * Load master component hosts data for using in required step controllers
  273. */
  274. loadMasterComponentHosts: function () {
  275. this._super();
  276. this.set('content.skipMasterStep', App.StackService.find().filterProperty('isSelected').filterProperty('hasMaster').everyProperty('isInstalled', true));
  277. this.get('isStepDisabled').findProperty('step', 2).set('value', this.get('content.skipMasterStep'));
  278. },
  279. /**
  280. * Does service have any configs
  281. * @param {string} serviceName
  282. * @returns {boolean}
  283. */
  284. isServiceNotConfigurable: function (serviceName) {
  285. return App.get('services.noConfigTypes').contains(serviceName);
  286. },
  287. /**
  288. * Should Config Step be skipped (based on selected services list)
  289. * @returns {boolean}
  290. */
  291. skipConfigStep: function () {
  292. var skipConfigStep = true;
  293. var selectedServices = this.get('content.services').filterProperty('isSelected', true).filterProperty('isInstalled', false).mapProperty('serviceName');
  294. selectedServices.map(function (serviceName) {
  295. skipConfigStep = skipConfigStep && this.isServiceNotConfigurable(serviceName);
  296. }, this);
  297. return skipConfigStep;
  298. },
  299. loadServiceConfigProperties: function () {
  300. this._super();
  301. if (!this.get('content.services')) {
  302. this.loadServices();
  303. }
  304. if (this.get('currentStep') > 1 && this.get('currentStep') < 6) {
  305. this.set('content.skipConfigStep', this.skipConfigStep());
  306. this.get('isStepDisabled').findProperty('step', 4).set('value', this.get('content.skipConfigStep'));
  307. }
  308. },
  309. /**
  310. * Load kerberos descriptor configuration
  311. * @returns {$.Deferred}
  312. */
  313. loadKerberosDescriptorConfigs: function() {
  314. var self = this,
  315. dfd = $.Deferred();
  316. if (App.router.get('mainAdminKerberosController.securityEnabled')) {
  317. this.getDescriptorConfigs().then(function(properties) {
  318. self.set('kerberosDescriptorConfigs', properties);
  319. dfd.resolve();
  320. });
  321. } else {
  322. dfd.resolve();
  323. }
  324. return dfd.promise();
  325. },
  326. saveServiceConfigProperties: function (stepController) {
  327. this._super(stepController);
  328. if (this.get('currentStep') > 1 && this.get('currentStep') < 6) {
  329. this.set('content.skipConfigStep', this.skipConfigStep());
  330. this.get('isStepDisabled').findProperty('step', 4).set('value', this.get('content.skipConfigStep'));
  331. }
  332. },
  333. /**
  334. * Load master component hosts data for using in required step controllers
  335. */
  336. loadSlaveComponentHosts: function () {
  337. var slaveComponentHosts = this.getDBProperty('slaveComponentHosts'),
  338. hosts = this.getDBProperty('hosts'),
  339. host_names = Em.keys(hosts);
  340. if (!Em.isNone(slaveComponentHosts)) {
  341. slaveComponentHosts.forEach(function (component) {
  342. component.hosts.forEach(function (host) {
  343. //Em.set(host, 'hostName', hosts[host.host_id].name);
  344. for (var i = 0; i < host_names.length; i++) {
  345. if (hosts[host_names[i]].id === host.host_id) {
  346. host.hostName = host_names[i];
  347. break;
  348. }
  349. }
  350. });
  351. });
  352. }
  353. if (!slaveComponentHosts) {
  354. slaveComponentHosts = this.getSlaveComponentHosts();
  355. }
  356. this.set("content.slaveComponentHosts", slaveComponentHosts);
  357. console.log("AddServiceController.loadSlaveComponentHosts: loaded hosts ", slaveComponentHosts);
  358. },
  359. /**
  360. * return slaveComponents bound to hosts
  361. * @return {Array}
  362. */
  363. getSlaveComponentHosts: function () {
  364. var components = this.get('slaveComponents');
  365. var result = [];
  366. var installedServices = App.Service.find().mapProperty('serviceName');
  367. var selectedServices = this.get('content.services').filterProperty('isSelected', true).mapProperty('serviceName');
  368. var installedComponentsMap = {};
  369. var uninstalledComponents = [];
  370. var hosts = this.getDBProperty('hosts') || this.get('content.hosts');
  371. var masterComponents = App.get('components.masters');
  372. var nonMasterComponentHosts = [];
  373. components.forEach(function (component) {
  374. if (installedServices.contains(component.get('serviceName'))) {
  375. installedComponentsMap[component.get('componentName')] = [];
  376. } else if (selectedServices.contains(component.get('serviceName'))) {
  377. uninstalledComponents.push(component);
  378. }
  379. }, this);
  380. for (var hostName in hosts) {
  381. if (hosts[hostName].isInstalled) {
  382. var isMasterComponentHosted = false;
  383. hosts[hostName].hostComponents.forEach(function (component) {
  384. if (installedComponentsMap[component.HostRoles.component_name]) {
  385. installedComponentsMap[component.HostRoles.component_name].push(hostName);
  386. }
  387. if (masterComponents.contains(component.HostRoles.component_name)) {
  388. isMasterComponentHosted = true;
  389. }
  390. }, this);
  391. if (!isMasterComponentHosted) {
  392. nonMasterComponentHosts.push(hostName);
  393. }
  394. }
  395. }
  396. for (var componentName in installedComponentsMap) {
  397. var component = {
  398. componentName: componentName,
  399. displayName: App.format.role(componentName),
  400. hosts: [],
  401. isInstalled: true
  402. };
  403. installedComponentsMap[componentName].forEach(function (hostName) {
  404. component.hosts.push({
  405. group: "Default",
  406. hostName: hostName,
  407. isInstalled: true
  408. });
  409. }, this);
  410. result.push(component);
  411. }
  412. if (!nonMasterComponentHosts.length) {
  413. nonMasterComponentHosts.push(Object.keys(hosts)[0]);
  414. }
  415. var uninstalledComponentHosts = nonMasterComponentHosts.map(function(_hostName){
  416. return {
  417. group: "Default",
  418. hostName: _hostName,
  419. isInstalled: false
  420. }
  421. });
  422. uninstalledComponents.forEach(function (component) {
  423. result.push({
  424. componentName: component.get('componentName'),
  425. displayName: App.format.role(component.get('componentName')),
  426. hosts: uninstalledComponentHosts,
  427. isInstalled: false
  428. })
  429. });
  430. return result;
  431. },
  432. /**
  433. * Generate clients list for selected services and save it to model
  434. * @param stepController step4WizardController
  435. */
  436. saveClients: function (stepController) {
  437. var clients = [];
  438. var serviceComponents = App.StackServiceComponent.find();
  439. this.get('content.services').filterProperty('isSelected').filterProperty('isInstalled',false).forEach(function (_service) {
  440. var serviceClients = serviceComponents.filterProperty('serviceName', _service.get('serviceName')).filterProperty('isClient');
  441. serviceClients.forEach(function (client) {
  442. clients.push({
  443. component_name: client.get('componentName'),
  444. display_name: client.get('displayName'),
  445. isInstalled: false
  446. });
  447. }, this);
  448. }, this);
  449. this.setDBProperty('clientInfo', clients);
  450. this.set('content.clients', clients);
  451. console.log("AddServiceController.saveClients: saved list ", clients);
  452. },
  453. /**
  454. * Remove all loaded data.
  455. * Created as copy for App.router.clearAllSteps
  456. */
  457. clearAllSteps: function () {
  458. this.clearInstallOptions();
  459. // clear temporary information stored during the install
  460. this.set('content.cluster', this.getCluster());
  461. },
  462. /**
  463. * Clear all temporary data
  464. */
  465. finish: function () {
  466. this.clearAllSteps();
  467. this.clearStorageData();
  468. this.resetDbNamespace();
  469. App.router.get('updateController').updateAll();
  470. },
  471. /**
  472. * genarates data for ajax request to launch install services
  473. * @method generateDataForInstallServices
  474. * @param {Array} selectedServices
  475. * @returns {{context: *, ServiceInfo: {state: string}, urlParams: string}}
  476. */
  477. generateDataForInstallServices: function(selectedServices) {
  478. if (selectedServices.contains('OOZIE')) {
  479. selectedServices = selectedServices.concat(['HDFS', 'YARN', 'MAPREDUCE2']);
  480. }
  481. return {
  482. "context": Em.I18n.t('requestInfo.installServices'),
  483. "ServiceInfo": {"state": "INSTALLED"},
  484. "urlParams": "ServiceInfo/service_name.in(" + selectedServices.join(',') + ")"
  485. };
  486. },
  487. /**
  488. * run this method after success/error callbacks
  489. * for <code>installServicesRequest<code>
  490. */
  491. installServicesComplete: function () {
  492. App.get('router.wizardStep8Controller').set('servicesInstalled', true);
  493. this.setInfoForStep9();
  494. this.saveClusterState('ADD_SERVICES_INSTALLING_3');
  495. App.router.transitionTo('step7');
  496. },
  497. /**
  498. * main method for installinf clients
  499. * @method installServices
  500. */
  501. installServices: function () {
  502. var self = this;
  503. this.set('content.cluster.oldRequestsId', []);
  504. this.installAdditionalClients().done(function () {
  505. self.installSelectedServices();
  506. });
  507. },
  508. installSelectedServices: function () {
  509. var name = 'common.services.update';
  510. var selectedServices = this.get('content.services').filterProperty('isInstalled', false).filterProperty('isSelected', true).mapProperty('serviceName');
  511. var data = this.generateDataForInstallServices(selectedServices);
  512. this.installServicesRequest(name, data, this.installServicesComplete.bind(this));
  513. },
  514. installServicesRequest: function (name, data, callback) {
  515. callback = callback || Em.K;
  516. App.ajax.send({
  517. name: name,
  518. sender: this,
  519. data: data,
  520. success: 'installServicesSuccessCallback',
  521. error: 'installServicesErrorCallback'
  522. }).then(callback, callback);
  523. },
  524. /**
  525. * installs clients before install new services
  526. * on host where some components require this
  527. * @method installAdditionalClients
  528. */
  529. installAdditionalClients: function () {
  530. var dfd = $.Deferred();
  531. if (this.get('content.additionalClients.length') > 0) {
  532. this.get('content.additionalClients').forEach(function (c, k) {
  533. if (c.hostNames.length > 0) {
  534. var queryStr = 'HostRoles/component_name='+ c.componentName + '&HostRoles/host_name.in(' + c.hostNames.join() + ')';
  535. this.get('installClietsQueue').addRequest({
  536. name: 'common.host_component.update',
  537. sender: this,
  538. data: {
  539. query: queryStr,
  540. context: 'Install ' + App.format.role(c.componentName),
  541. HostRoles: {
  542. state: 'INSTALLED'
  543. },
  544. counter: k,
  545. deferred: dfd
  546. },
  547. success: 'installClientSuccess',
  548. error: 'installClientError'
  549. });
  550. }
  551. }, this);
  552. if (this.get('installClietsQueue.queue.length') == 0) {
  553. return dfd.resolve();
  554. } else {
  555. this.set('installClientQueueLength', this.get('installClietsQueue.queue.length'));
  556. App.get('router.wizardStep8Controller').set('servicesInstalled', true);
  557. this.get('installClietsQueue').start();
  558. }
  559. } else {
  560. dfd.resolve();
  561. }
  562. return dfd.promise();
  563. },
  564. /**
  565. * callback for when install clients success
  566. * @param data
  567. * @param opt
  568. * @param params
  569. * @method installClientComplete
  570. */
  571. installClientSuccess: function(data, opt, params) {
  572. if (this.get('installClientQueueLength') - 1 == params.counter) {
  573. params.deferred.resolve();
  574. }
  575. },
  576. /**
  577. * callback for when install clients fail
  578. * @param request
  579. * @param ajaxOptions
  580. * @param error
  581. * @param opt
  582. * @param params
  583. */
  584. installClientError: function(request, ajaxOptions, error, opt, params) {
  585. if (this.get('installClientQueueLength') - 1 == params.counter) {
  586. params.deferred.resolve();
  587. }
  588. },
  589. checkSecurityStatus: function() {
  590. if (App.supports.automatedKerberos) {
  591. if (!App.router.get('mainAdminKerberosController.securityEnabled')) {
  592. this.set('skipConfigureIdentitiesStep', true);
  593. this.get('isStepDisabled').findProperty('step', 5).set('value', true);
  594. }
  595. }
  596. }
  597. });