add_controller.js 21 KB

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