add_controller.js 19 KB

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