step4_controller.js 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  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.ReassignMasterWizardStep4Controller = App.HighAvailabilityProgressPageController.extend({
  20. isReassign: true,
  21. commands: ['stopServices', 'cleanMySqlServer', 'createHostComponents', 'putHostComponentsInMaintenanceMode', 'reconfigure', 'installHostComponents', 'startZooKeeperServers', 'startNameNode', 'deleteHostComponents', 'configureMySqlServer',
  22. 'startMySqlServer', 'startNewMySqlServer' , 'startServices'],
  23. // custom commands for Components with DB Configuration and Check
  24. commandsForDB: ['createHostComponents', 'installHostComponents', 'configureMySqlServer', 'startMySqlServer', 'testDBConnection', 'stopServices', 'cleanMySqlServer', 'putHostComponentsInMaintenanceMode', 'reconfigure', 'deleteHostComponents', 'configureMySqlServer', 'startServices'],
  25. clusterDeployState: 'REASSIGN_MASTER_INSTALLING',
  26. multiTaskCounter: 0,
  27. hostComponents: [],
  28. /**
  29. * Map with lists of unrelated services.
  30. * Used to define list of services to stop/start.
  31. */
  32. unrelatedServicesMap: {
  33. 'JOBTRACKER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM'],
  34. 'RESOURCEMANAGER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM'],
  35. 'APP_TIMELINE_SERVER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM'],
  36. 'OOZIE_SERVER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM', 'HIVE'],
  37. 'WEBHCAT_SERVER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM'],
  38. 'HIVE_SERVER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM'],
  39. 'HIVE_METASTORE': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM'],
  40. 'MYSQL_SERVER': ['HDFS', 'ZOOKEEPER', 'HBASE', 'FLUME', 'SQOOP', 'STORM']
  41. },
  42. /**
  43. * additional configs with template values
  44. * Part of value to substitute has following format: "<replace-value>"
  45. */
  46. additionalConfigsMap: [
  47. {
  48. componentName: 'RESOURCEMANAGER',
  49. configs: {
  50. 'yarn-site': {
  51. 'yarn.resourcemanager.address': '<replace-value>:8050',
  52. 'yarn.resourcemanager.admin.address': '<replace-value>:8141',
  53. 'yarn.resourcemanager.resource-tracker.address': '<replace-value>:8025',
  54. 'yarn.resourcemanager.scheduler.address': '<replace-value>:8030',
  55. 'yarn.resourcemanager.webapp.address': '<replace-value>:8088',
  56. 'yarn.resourcemanager.hostname': '<replace-value>'
  57. }
  58. }
  59. },
  60. {
  61. componentName: 'JOBTRACKER',
  62. configs: {
  63. 'mapred-site': {
  64. 'mapred.job.tracker.http.address': '<replace-value>:50030',
  65. 'mapred.job.tracker': '<replace-value>:50300'
  66. }
  67. }
  68. },
  69. {
  70. componentName: 'SECONDARY_NAMENODE',
  71. configs: {
  72. 'hdfs-site': {
  73. 'dfs.secondary.http.address': '<replace-value>:50090'
  74. }
  75. },
  76. configs_Hadoop2: {
  77. 'hdfs-site': {
  78. 'dfs.namenode.secondary.http-address': '<replace-value>:50090'
  79. }
  80. }
  81. },
  82. {
  83. componentName: 'NAMENODE',
  84. configs: {
  85. 'hdfs-site': {
  86. 'dfs.http.address': '<replace-value>:50070',
  87. 'dfs.https.address': '<replace-value>:50470'
  88. },
  89. 'core-site': {
  90. 'fs.default.name': 'hdfs://<replace-value>:8020'
  91. }
  92. },
  93. configs_Hadoop2: {
  94. 'hdfs-site': {
  95. 'dfs.namenode.http-address': '<replace-value>:50070',
  96. 'dfs.namenode.https-address': '<replace-value>:50470'
  97. },
  98. 'core-site': {
  99. 'fs.defaultFS': 'hdfs://<replace-value>:8020'
  100. }
  101. }
  102. },
  103. {
  104. componentName: 'APP_TIMELINE_SERVER',
  105. configs: {
  106. 'yarn-site': {
  107. 'yarn.timeline-service.webapp.address': '<replace-value>:8188',
  108. 'yarn.timeline-service.webapp.https.address': '<replace-value>:8190',
  109. 'yarn.timeline-service.address': '<replace-value>:10200'
  110. }
  111. }
  112. },
  113. {
  114. componentName: 'OOZIE_SERVER',
  115. configs: {
  116. 'oozie-site': {
  117. 'oozie.base.url': 'http://<replace-value>:11000/oozie'
  118. },
  119. 'core-site': {
  120. 'hadoop.proxyuser.oozie.hosts': '<replace-value>'
  121. }
  122. }
  123. },
  124. {
  125. componentName: 'HIVE_METASTORE',
  126. configs: {
  127. 'hive-site': {}
  128. }
  129. },
  130. {
  131. componentName: 'MYSQL_SERVER',
  132. configs: {
  133. 'hive-site': {
  134. 'javax.jdo.option.ConnectionURL': 'jdbc:mysql://<replace-value>/hive?createDatabaseIfNotExist=true'
  135. }
  136. }
  137. }
  138. ],
  139. secureConfigsMap: [
  140. {
  141. componentName: 'NAMENODE',
  142. configs: [
  143. {
  144. site: 'hdfs-site',
  145. keytab: 'dfs.namenode.keytab.file',
  146. principal: 'dfs.namenode.kerberos.principal'
  147. },
  148. {
  149. site: 'hdfs-site',
  150. keytab: 'dfs.web.authentication.kerberos.keytab',
  151. principal: 'dfs.web.authentication.kerberos.principal'
  152. }
  153. ]
  154. },
  155. {
  156. componentName: 'SECONDARY_NAMENODE',
  157. configs: [
  158. {
  159. site: 'hdfs-site',
  160. keytab: 'dfs.secondary.namenode.keytab.file',
  161. principal: 'dfs.secondary.namenode.kerberos.principal'
  162. },
  163. {
  164. site: 'hdfs-site',
  165. keytab: 'dfs.web.authentication.kerberos.keytab',
  166. principal: 'dfs.web.authentication.kerberos.principal'
  167. }
  168. ]
  169. },
  170. {
  171. componentName: 'RESOURCEMANAGER',
  172. configs: [
  173. {
  174. site: 'yarn-site',
  175. keytab: 'yarn.resourcemanager.keytab',
  176. principal: 'yarn.resourcemanager.principal'
  177. },
  178. {
  179. site: 'yarn-site',
  180. keytab: 'yarn.resourcemanager.webapp.spnego-keytab-file',
  181. principal: 'yarn.resourcemanager.webapp.spnego-principal'
  182. }
  183. ]
  184. },
  185. {
  186. componentName: 'OOZIE_SERVER',
  187. configs: [
  188. {
  189. site: 'oozie-site',
  190. keytab: 'oozie.authentication.kerberos.keytab',
  191. principal: 'oozie.authentication.kerberos.principal'
  192. },
  193. {
  194. site: 'oozie-site',
  195. keytab: 'oozie.service.HadoopAccessorService.keytab.file',
  196. principal: 'oozie.service.HadoopAccessorService.kerberos.principal'
  197. }
  198. ]
  199. },
  200. {
  201. componentName: 'WEBHCAT_SERVER',
  202. configs: [
  203. {
  204. site: 'webhcat-site',
  205. keytab: 'templeton.kerberos.keytab',
  206. principal: 'templeton.kerberos.principal'
  207. }
  208. ]
  209. },
  210. {
  211. componentName: 'HIVE_SERVER',
  212. configs: [
  213. {
  214. site: 'hive-site',
  215. keytab: 'hive.server2.authentication.kerberos.keytab',
  216. principal: 'hive.server2.authentication.kerberos.principal'
  217. },
  218. {
  219. site: 'hive-site',
  220. keytab: 'hive.server2.authentication.spnego.keytab',
  221. principal: 'hive.server2.authentication.spnego.principal'
  222. }
  223. ]
  224. },
  225. {
  226. componentName: 'HIVE_METASTORE',
  227. configs: [
  228. {
  229. site: 'hive-site',
  230. keytab: 'hive.metastore.kerberos.keytab.file',
  231. principal: 'hive.metastore.kerberos.principal'
  232. }
  233. ]
  234. }
  235. ],
  236. /**
  237. * set additional configs
  238. * configs_Hadoop2 - configs which belongs to Hadoop 2 stack only
  239. * @param configs
  240. * @param componentName
  241. * @param replaceValue
  242. * @return {Boolean}
  243. */
  244. setAdditionalConfigs: function (configs, componentName, replaceValue) {
  245. var component = this.get('additionalConfigsMap').findProperty('componentName', componentName);
  246. if (Em.isNone(component)) return false;
  247. var additionalConfigs = (component.configs_Hadoop2) ? component.configs_Hadoop2 : component.configs;
  248. for (var site in additionalConfigs) {
  249. if (additionalConfigs.hasOwnProperty(site)) {
  250. for (var property in additionalConfigs[site]) {
  251. if (additionalConfigs[site].hasOwnProperty(property)) {
  252. if (App.get('isHaEnabled') && componentName === 'NAMENODE' && property === 'fs.defaultFS') continue;
  253. configs[site][property] = additionalConfigs[site][property].replace('<replace-value>', replaceValue);
  254. }
  255. }
  256. }
  257. }
  258. return true;
  259. },
  260. /**
  261. * load step info
  262. */
  263. loadStep: function () {
  264. if (this.get('content.reassign.component_name') === 'NAMENODE' && App.get('isHaEnabled')) {
  265. this.set('hostComponents', ['NAMENODE', 'ZKFC']);
  266. } else {
  267. this.set('hostComponents', [this.get('content.reassign.component_name')]);
  268. }
  269. this.set('serviceName', [this.get('content.reassign.service_id')]);
  270. this._super();
  271. },
  272. /**
  273. * concat host-component names into string
  274. * @return {String}
  275. */
  276. getHostComponentsNames: function () {
  277. var hostComponentsNames = '';
  278. this.get('hostComponents').forEach(function (comp, index) {
  279. hostComponentsNames += index ? '+' : '';
  280. hostComponentsNames += comp === 'ZKFC' ? comp : App.format.role(comp);
  281. }, this);
  282. return hostComponentsNames;
  283. },
  284. /**
  285. * remove unneeded tasks
  286. */
  287. removeUnneededTasks: function () {
  288. if(this.isComponentWithDB()) {
  289. var db_type = this.get('content.databaseType');
  290. var is_remote_db = this.get('content.serviceProperties.is_remote_db');
  291. if(is_remote_db || db_type !== 'mysql') {
  292. this.removeTasks(['configureMySqlServer', 'startMySqlServer', 'cleanMySqlServer', 'configureMySqlServer']);
  293. }
  294. if (db_type === 'derby') {
  295. this.removeTasks(['testDBConnection']);
  296. }
  297. }
  298. if ( this.get('content.reassign.component_name') !== 'MYSQL_SERVER' && !this.isComponentWithDB()) {
  299. this.removeTasks(['configureMySqlServer', 'startMySqlServer', 'cleanMySqlServer', 'startNewMySqlServer', 'configureMySqlServer']);
  300. }
  301. if ( this.get('content.reassign.component_name') === 'MYSQL_SERVER' ) {
  302. this.removeTasks(['cleanMySqlServer']);
  303. }
  304. if (this.get('content.hasManualSteps')) {
  305. if (this.get('content.reassign.component_name') === 'NAMENODE' && App.get('isHaEnabled')) {
  306. // Only for reassign NameNode with HA enabled
  307. this.removeTasks(['deleteHostComponents', 'startServices']);
  308. } else {
  309. this.removeTasks(['startZooKeeperServers', 'startNameNode', 'deleteHostComponents', 'startServices']);
  310. }
  311. } else {
  312. this.removeTasks(['startZooKeeperServers', 'startNameNode']);
  313. }
  314. },
  315. /**
  316. * remove tasks by command name
  317. */
  318. removeTasks: function(commands) {
  319. var tasks = this.get('tasks');
  320. commands.forEach(function(command) {
  321. var cmd = tasks.filterProperty('command', command);
  322. var index = null;
  323. if (cmd.length === 0) {
  324. return false;
  325. } else {
  326. index = tasks.indexOf( cmd[0] );
  327. }
  328. tasks.splice( index, 1 );
  329. });
  330. },
  331. /**
  332. * initialize tasks
  333. */
  334. initializeTasks: function () {
  335. var commands = this.get('commands');
  336. var currentStep = App.router.get('reassignMasterController.currentStep');
  337. var hostComponentsNames = this.getHostComponentsNames();
  338. if (this.isComponentWithDB()) {
  339. commands = this.get('commandsForDB');
  340. }
  341. for (var i = 0; i < commands.length; i++) {
  342. var TaskLabel = i === 3 ? this.get('serviceName') : hostComponentsNames; //For Reconfigure task, show serviceName
  343. var title = Em.I18n.t('services.reassign.step4.tasks.' + commands[i] + '.title').format(TaskLabel);
  344. this.get('tasks').pushObject(Ember.Object.create({
  345. title: title,
  346. status: 'PENDING',
  347. id: i,
  348. command: commands[i],
  349. showRetry: false,
  350. showRollback: false,
  351. name: title,
  352. displayName: title,
  353. progress: 0,
  354. isRunning: false,
  355. hosts: []
  356. }));
  357. }
  358. this.removeUnneededTasks();
  359. this.set('isLoaded', true);
  360. },
  361. hideRollbackButton: function () {
  362. var failedTask = this.get('tasks').findProperty('showRollback');
  363. if (failedTask) {
  364. failedTask.set('showRollback', false);
  365. }
  366. }.observes('tasks.@each.showRollback'),
  367. onComponentsTasksSuccess: function () {
  368. this.incrementProperty('multiTaskCounter');
  369. if (this.get('multiTaskCounter') >= this.get('hostComponents').length) {
  370. this.onTaskCompleted();
  371. }
  372. },
  373. /**
  374. * compute data for call to stop services
  375. * @return {Object}
  376. */
  377. getStopServicesData: function () {
  378. var data = {
  379. "ServiceInfo": {
  380. "state": "INSTALLED"
  381. }
  382. };
  383. var unrelatedServices = this.get('unrelatedServicesMap')[this.get('content.reassign.component_name')];
  384. if (unrelatedServices) {
  385. var list = App.Service.find().mapProperty("serviceName").filter(function (s) {
  386. return !unrelatedServices.contains(s)
  387. }).join(',');
  388. data.context = "Stop required services";
  389. data.urlParams = "ServiceInfo/service_name.in(" + list + ")";
  390. } else {
  391. data.context = "Stop all services";
  392. }
  393. return data;
  394. },
  395. /**
  396. * make server call to stop services
  397. */
  398. stopServices: function () {
  399. App.ajax.send({
  400. name: 'common.services.update',
  401. sender: this,
  402. data: this.getStopServicesData(),
  403. success: 'startPolling',
  404. error: 'onTaskError'
  405. });
  406. },
  407. createHostComponents: function () {
  408. this.set('multiTaskCounter', 0);
  409. var hostComponents = this.get('hostComponents');
  410. var hostName = this.get('content.reassignHosts.target');
  411. for (var i = 0; i < hostComponents.length; i++) {
  412. this.createComponent(hostComponents[i], hostName, this.get('content.reassign.service_id'));
  413. }
  414. },
  415. onCreateComponent: function () {
  416. this.onComponentsTasksSuccess();
  417. },
  418. putHostComponentsInMaintenanceMode: function () {
  419. this.set('multiTaskCounter', 0);
  420. var hostComponents = this.get('hostComponents');
  421. var hostName = this.get('content.reassignHosts.source');
  422. for (var i = 0; i < hostComponents.length; i++) {
  423. App.ajax.send({
  424. name: 'common.host.host_component.passive',
  425. sender: this,
  426. data: {
  427. hostName: hostName,
  428. passive_state: "ON",
  429. componentName: hostComponents[i]
  430. },
  431. success: 'onComponentsTasksSuccess',
  432. error: 'onTaskError'
  433. });
  434. }
  435. },
  436. installHostComponents: function () {
  437. this.set('multiTaskCounter', 0);
  438. var hostComponents = this.get('hostComponents');
  439. var hostName = this.get('content.reassignHosts.target');
  440. for (var i = 0; i < hostComponents.length; i++) {
  441. this.updateComponent(hostComponents[i], hostName, this.get('content.reassign.service_id'), "Install", hostComponents.length);
  442. }
  443. },
  444. reconfigure: function () {
  445. this.loadConfigsTags();
  446. },
  447. loadConfigsTags: function () {
  448. App.ajax.send({
  449. name: 'config.tags',
  450. sender: this,
  451. success: 'onLoadConfigsTags',
  452. error: 'onTaskError'
  453. });
  454. },
  455. /**
  456. * construct URL parameters for config call
  457. * @param componentName
  458. * @param data
  459. * @return {Array}
  460. */
  461. getConfigUrlParams: function (componentName, data) {
  462. var urlParams = [];
  463. switch (componentName) {
  464. case 'NAMENODE':
  465. urlParams.push('(type=hdfs-site&tag=' + data.Clusters.desired_configs['hdfs-site'].tag + ')');
  466. urlParams.push('(type=core-site&tag=' + data.Clusters.desired_configs['core-site'].tag + ')');
  467. if (App.Service.find().someProperty('serviceName', 'HBASE')) {
  468. urlParams.push('(type=hbase-site&tag=' + data.Clusters.desired_configs['hbase-site'].tag + ')');
  469. }
  470. break;
  471. case 'SECONDARY_NAMENODE':
  472. urlParams.push('(type=hdfs-site&tag=' + data.Clusters.desired_configs['hdfs-site'].tag + ')');
  473. urlParams.push('(type=core-site&tag=' + data.Clusters.desired_configs['core-site'].tag + ')');
  474. break;
  475. case 'JOBTRACKER':
  476. urlParams.push('(type=mapred-site&tag=' + data.Clusters.desired_configs['mapred-site'].tag + ')');
  477. break;
  478. case 'RESOURCEMANAGER':
  479. urlParams.push('(type=yarn-site&tag=' + data.Clusters.desired_configs['yarn-site'].tag + ')');
  480. break;
  481. case 'WEBHCAT_SERVER':
  482. urlParams.push('(type=webhcat-site&tag=' + data.Clusters.desired_configs['webhcat-site'].tag + ')');
  483. break;
  484. case 'APP_TIMELINE_SERVER':
  485. urlParams.push('(type=yarn-site&tag=' + data.Clusters.desired_configs['yarn-site'].tag + ')');
  486. urlParams.push('(type=yarn-env&tag=' + data.Clusters.desired_configs['yarn-env'].tag + ')');
  487. break;
  488. case 'OOZIE_SERVER':
  489. urlParams.push('(type=oozie-site&tag=' + data.Clusters.desired_configs['oozie-site'].tag + ')');
  490. urlParams.push('(type=core-site&tag=' + data.Clusters.desired_configs['core-site'].tag + ')');
  491. break;
  492. case 'HIVE_SERVER':
  493. case 'HIVE_METASTORE':
  494. urlParams.push('(type=hive-site&tag=' + data.Clusters.desired_configs['hive-site'].tag + ')');
  495. urlParams.push('(type=webhcat-site&tag=' + data.Clusters.desired_configs['webhcat-site'].tag + ')');
  496. urlParams.push('(type=hive-env&tag=' + data.Clusters.desired_configs['hive-env'].tag + ')');
  497. urlParams.push('(type=core-site&tag=' + data.Clusters.desired_configs['core-site'].tag + ')');
  498. break;
  499. case 'MYSQL_SERVER':
  500. urlParams.push('(type=hive-site&tag=' + data.Clusters.desired_configs['hive-site'].tag + ')');
  501. break;
  502. }
  503. return urlParams;
  504. },
  505. onLoadConfigsTags: function (data) {
  506. var urlParams = this.getConfigUrlParams(this.get('content.reassign.component_name'), data);
  507. App.ajax.send({
  508. name: 'reassign.load_configs',
  509. sender: this,
  510. data: {
  511. urlParams: urlParams.join('|')
  512. },
  513. success: 'onLoadConfigs',
  514. error: 'onTaskError'
  515. });
  516. },
  517. onLoadConfigs: function (data) {
  518. var componentName = this.get('content.reassign.component_name');
  519. var targetHostName = this.get('content.reassignHosts.target');
  520. var configs = {};
  521. var secureConfigs = [];
  522. data.items.forEach(function (item) {
  523. configs[item.type] = item.properties;
  524. }, this);
  525. this.setAdditionalConfigs(configs, componentName, targetHostName);
  526. this.setSecureConfigs(secureConfigs, configs, componentName);
  527. if (componentName === 'NAMENODE') {
  528. this.setSpecificNamenodeConfigs(configs, targetHostName);
  529. }
  530. if (componentName === 'RESOURCEMANAGER') {
  531. this.setSpecificResourceMangerConfigs(configs, targetHostName);
  532. }
  533. if (componentName === 'HIVE_METASTORE' || componentName === 'HIVE_SERVER') {
  534. this.setSpecificHiveConfigs(configs, targetHostName);
  535. }
  536. this.saveClusterStatus(secureConfigs, this.getComponentDir(configs, componentName));
  537. this.saveConfigsToServer(configs);
  538. this.saveServiceProperties(configs);
  539. },
  540. /**
  541. * make PUT call to save configs to server
  542. * @param configs
  543. */
  544. saveConfigsToServer: function (configs) {
  545. App.ajax.send({
  546. name: 'common.across.services.configurations',
  547. sender: this,
  548. data: {
  549. data: '[' + this.getServiceConfigData(configs).toString() + ']'
  550. },
  551. success: 'onSaveConfigs',
  552. error: 'onTaskError'
  553. });
  554. },
  555. /**
  556. * gather and format config data before sending to server
  557. * @param configs
  558. * @return {Array}
  559. * @method getServiceConfigData
  560. */
  561. getServiceConfigData: function (configs) {
  562. var componentName = this.get('content.reassign.component_name');
  563. var tagName = 'version' + (new Date).getTime();
  564. var configData = Object.keys(configs).map(function (_siteName) {
  565. return {
  566. type: _siteName,
  567. tag: tagName,
  568. properties: configs[_siteName],
  569. service_config_version_note: Em.I18n.t('services.reassign.step4.save.configuration.note').format(App.format.role(componentName))
  570. }
  571. });
  572. var allConfigData = [];
  573. App.Service.find().forEach(function (service) {
  574. var stackService = App.StackService.find().findProperty('serviceName', service.get('serviceName'));
  575. if (stackService) {
  576. var serviceConfigData = [];
  577. Object.keys(stackService.get('configTypesRendered')).forEach(function (type) {
  578. var serviceConfigTag = configData.findProperty('type', type);
  579. if (serviceConfigTag) {
  580. serviceConfigData.pushObject(serviceConfigTag);
  581. }
  582. }, this);
  583. allConfigData.pushObject(JSON.stringify({
  584. Clusters: {
  585. desired_config: serviceConfigData
  586. }
  587. }));
  588. }
  589. }, this);
  590. return allConfigData;
  591. },
  592. /**
  593. * set specific configs which applies only to NameNode component
  594. * @param configs
  595. * @param targetHostName
  596. */
  597. setSpecificNamenodeConfigs: function (configs, targetHostName) {
  598. var sourceHostName = this.get('content.reassignHosts.source');
  599. if (App.get('isHaEnabled')) {
  600. var nameServices = configs['hdfs-site']['dfs.nameservices'];
  601. var suffix = (configs['hdfs-site']['dfs.namenode.http-address.' + nameServices + '.nn1'] === sourceHostName + ':50070') ? '.nn1' : '.nn2';
  602. configs['hdfs-site']['dfs.namenode.http-address.' + nameServices + suffix] = targetHostName + ':50070';
  603. configs['hdfs-site']['dfs.namenode.https-address.' + nameServices + suffix] = targetHostName + ':50470';
  604. configs['hdfs-site']['dfs.namenode.rpc-address.' + nameServices + suffix] = targetHostName + ':8020';
  605. }
  606. if (!App.get('isHaEnabled') && App.Service.find('HBASE').get('isLoaded')) {
  607. configs['hbase-site']['hbase.rootdir'] = configs['hbase-site']['hbase.rootdir'].replace(/\/\/[^\/]*/, '//' + targetHostName + ':8020');
  608. }
  609. },
  610. /**
  611. * set specific configs which applies only to ResourceManager component
  612. * @param configs
  613. * @param targetHostName
  614. */
  615. setSpecificResourceMangerConfigs: function (configs, targetHostName) {
  616. var sourceHostName = this.get('content.reassignHosts.source');
  617. if (App.get('isRMHaEnabled')) {
  618. if (configs['yarn-site']['yarn.resourcemanager.hostname.rm1'] === sourceHostName) {
  619. configs['yarn-site']['yarn.resourcemanager.hostname.rm1'] = targetHostName;
  620. } else {
  621. configs['yarn-site']['yarn.resourcemanager.hostname.rm2'] = targetHostName;
  622. }
  623. }
  624. },
  625. /**
  626. * set specific configs which applies only to Hive related configs
  627. * @param configs
  628. * @param targetHostName
  629. */
  630. setSpecificHiveConfigs: function (configs, targetHostName) {
  631. var sourceHostName = this.get('content.reassignHosts.source');
  632. var hiveMSHosts = App.HostComponent.find().filterProperty('componentName', 'HIVE_METASTORE').mapProperty('hostName');
  633. if (this.get('content.reassign.component_name') === 'HIVE_METASTORE') hiveMSHosts = hiveMSHosts.removeObject(sourceHostName).addObject(targetHostName);
  634. var hiveServerHosts = App.HostComponent.find().filterProperty('componentName', 'HIVE_SERVER').mapProperty('hostName');
  635. if (this.get('content.reassign.component_name') === 'HIVE_SERVER') hiveServerHosts = hiveServerHosts.removeObject(sourceHostName).addObject(targetHostName);
  636. var hiveMasterHosts = hiveMSHosts.concat(hiveServerHosts).uniq().join(',');
  637. var hiveUser = configs['hive-env']['hive_user'];
  638. var webhcatUser = configs['hive-env']['webhcat_user'];
  639. var port = configs['hive-site']['hive.metastore.uris'].match(/:[0-9]{2,4}/);
  640. port = port ? port[0].slice(1) : "9083";
  641. for (var i = 0; i < hiveMSHosts.length; i++) {
  642. hiveMSHosts[i] = "thrift://" + hiveMSHosts[i] + ":" + port;
  643. }
  644. configs['hive-site']['hive.metastore.uris'] = hiveMSHosts.join(',');
  645. configs['webhcat-site']['templeton.hive.properties'] = configs['webhcat-site']['templeton.hive.properties'].replace(/thrift.+[0-9]{2,},/i, hiveMSHosts.join('\\,') + ",");
  646. configs['core-site']['hadoop.proxyuser.' + hiveUser + '.hosts'] = hiveMasterHosts;
  647. configs['core-site']['hadoop.proxyuser.' + webhcatUser + '.hosts'] = hiveMasterHosts;
  648. },
  649. /**
  650. * set secure configs for component
  651. * @param secureConfigs
  652. * @param configs
  653. * @param componentName
  654. * @return {Boolean}
  655. */
  656. setSecureConfigs: function (secureConfigs, configs, componentName) {
  657. var securityEnabled = this.get('content.securityEnabled');
  658. var component = this.get('secureConfigsMap').findProperty('componentName', componentName);
  659. if (Em.isNone(component) || !securityEnabled) return false;
  660. component.configs.forEach(function (config) {
  661. secureConfigs.push({
  662. keytab: configs[config.site][config.keytab],
  663. principal: configs[config.site][config.principal]
  664. });
  665. });
  666. return true;
  667. },
  668. /**
  669. * derive component directory from configurations
  670. * @param configs
  671. * @param componentName
  672. * @return {String}
  673. */
  674. getComponentDir: function (configs, componentName) {
  675. if (componentName === 'NAMENODE') {
  676. return configs['hdfs-site']['dfs.namenode.name.dir'];
  677. } else if (componentName === 'SECONDARY_NAMENODE') {
  678. return configs['hdfs-site']['dfs.namenode.checkpoint.dir'];
  679. }
  680. return '';
  681. },
  682. /**
  683. * save cluster status to server
  684. *
  685. * @param secureConfigs
  686. * @param componentDir
  687. * @return {Boolean}
  688. */
  689. saveClusterStatus: function (secureConfigs, componentDir) {
  690. if (componentDir || secureConfigs.length) {
  691. App.router.get(this.get('content.controllerName')).saveComponentDir(componentDir);
  692. App.router.get(this.get('content.controllerName')).saveSecureConfigs(secureConfigs);
  693. App.clusterStatus.setClusterStatus({
  694. clusterName: this.get('content.cluster.name'),
  695. clusterState: this.get('clusterDeployState'),
  696. wizardControllerName: this.get('content.controllerName'),
  697. localdb: App.db.data
  698. });
  699. return true;
  700. }
  701. return false;
  702. },
  703. onSaveConfigs: function () {
  704. this.onTaskCompleted();
  705. },
  706. startZooKeeperServers: function () {
  707. var components = this.get('content.masterComponentHosts').filterProperty('component', 'ZOOKEEPER_SERVER');
  708. this.updateComponent('ZOOKEEPER_SERVER', components.mapProperty('hostName'), "ZOOKEEPER", "Start");
  709. },
  710. startNameNode: function () {
  711. var components = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE');
  712. this.updateComponent('NAMENODE', components.mapProperty('hostName').without(this.get('content.reassignHosts.source')), "HDFS", "Start");
  713. },
  714. /**
  715. * make server call to start services
  716. */
  717. startServices: function () {
  718. App.ajax.send({
  719. name: 'common.services.update',
  720. sender: this,
  721. data: this.getStartServicesData(),
  722. success: 'startPolling',
  723. error: 'onTaskError'
  724. });
  725. },
  726. /**
  727. * compute data for call to start services
  728. * @return {Object}
  729. */
  730. getStartServicesData: function () {
  731. var unrelatedServices = this.get('unrelatedServicesMap')[this.get('content.reassign.component_name')];
  732. var data = {};
  733. if (unrelatedServices) {
  734. var list = App.Service.find().mapProperty("serviceName").filter(function (s) {
  735. return !unrelatedServices.contains(s)
  736. }).join(',');
  737. data = {
  738. "context": "Start required services",
  739. "ServiceInfo": {
  740. "state": "STARTED"
  741. },
  742. "urlParams": "ServiceInfo/service_name.in(" + list + ")"
  743. };
  744. } else {
  745. data = {
  746. "context": "Start all services",
  747. "ServiceInfo": {
  748. "state": "STARTED"
  749. },
  750. "urlParams": "params/run_smoke_test=true"
  751. };
  752. }
  753. return data;
  754. },
  755. /**
  756. * make DELETE call for each host component on host
  757. */
  758. deleteHostComponents: function () {
  759. this.set('multiTaskCounter', 0);
  760. var hostComponents = this.get('hostComponents');
  761. var hostName = this.get('content.reassignHosts.source');
  762. for (var i = 0; i < hostComponents.length; i++) {
  763. App.ajax.send({
  764. name: 'common.delete.host_component',
  765. sender: this,
  766. data: {
  767. hostName: hostName,
  768. componentName: hostComponents[i]
  769. },
  770. success: 'onComponentsTasksSuccess',
  771. error: 'onDeleteHostComponentsError'
  772. });
  773. }
  774. },
  775. onDeleteHostComponentsError: function (error) {
  776. if (error.responseText.indexOf('org.apache.ambari.server.controller.spi.NoSuchResourceException') !== -1) {
  777. this.onComponentsTasksSuccess();
  778. } else {
  779. this.onTaskError();
  780. }
  781. },
  782. done: function () {
  783. if (!this.get('isSubmitDisabled')) {
  784. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  785. if (this.get('content.hasManualSteps')) {
  786. App.router.send('next');
  787. } else {
  788. App.router.send('complete');
  789. }
  790. }
  791. },
  792. /**
  793. * make server call to clean MYSQL
  794. */
  795. cleanMySqlServer: function () {
  796. var hostname = App.HostComponent.find().filterProperty('componentName', 'MYSQL_SERVER').get('firstObject.hostName');
  797. if (this.get('content.reassign.component_name') === 'MYSQL_SERVER') {
  798. hostname = this.get('content.reassignHosts.target');
  799. }
  800. App.ajax.send({
  801. name: 'service.mysql.clean',
  802. sender: this,
  803. data: {
  804. host: hostname
  805. },
  806. success: 'startPolling',
  807. error: 'onTaskError'
  808. });
  809. },
  810. /**
  811. * make server call to configure MYSQL
  812. */
  813. configureMySqlServer : function () {
  814. var hostname = App.HostComponent.find().filterProperty('componentName', 'MYSQL_SERVER').get('firstObject.hostName');
  815. if (this.get('content.reassign.component_name') === 'MYSQL_SERVER') {
  816. hostname = this.get('content.reassignHosts.target');
  817. }
  818. App.ajax.send({
  819. name: 'service.mysql.configure',
  820. sender: this,
  821. data: {
  822. host: hostname
  823. },
  824. success: 'startPolling',
  825. error: 'onTaskError'
  826. });
  827. },
  828. startMySqlServer: function() {
  829. App.ajax.send({
  830. name: 'common.host.host_component.update',
  831. sender: this,
  832. data: {
  833. context: "Start MySQL Server",
  834. hostName: App.HostComponent.find().filterProperty('componentName', 'MYSQL_SERVER').get('firstObject.hostName'),
  835. serviceName: "HIVE",
  836. componentName: "MYSQL_SERVER",
  837. HostRoles: {
  838. state: "STARTED"
  839. }
  840. },
  841. success: 'startPolling',
  842. error: 'onTaskError'
  843. });
  844. },
  845. startNewMySqlServer: function() {
  846. App.ajax.send({
  847. name: 'common.host.host_component.update',
  848. sender: this,
  849. data: {
  850. context: "Start MySQL Server",
  851. hostName: this.get('content.reassignHosts.target'),
  852. serviceName: "HIVE",
  853. componentName: "MYSQL_SERVER",
  854. HostRoles: {
  855. state: "STARTED"
  856. }
  857. },
  858. success: 'startPolling',
  859. error: 'onTaskError'
  860. });
  861. },
  862. testDBConnection: function() {
  863. this.prepareDBCheckAction();
  864. // this.onTaskCompleted();
  865. },
  866. isComponentWithDB: function() {
  867. return ['HIVE_SERVER', 'HIVE_METASTORE', 'OOZIE_SERVER'].contains(this.get('content.reassign.component_name'));
  868. },
  869. dbProperty: function() {
  870. var componentName = this.get('content.reassign.component_name');
  871. var property = null;
  872. switch(componentName) {
  873. case 'HIVE_SERVER':
  874. case 'HIVE_METASTORE':
  875. property = 'javax.jdo.option.ConnectionDriverName';
  876. break;
  877. case 'OOZIE_SERVER':
  878. property = 'oozie.service.JPAService.jdbc.url';
  879. break;
  880. }
  881. return property;
  882. }.property(),
  883. /** @property {Object} propertiesPattern - check pattern according to type of connection properties **/
  884. propertiesPattern: function() {
  885. return {
  886. user_name: /(username|dblogin)$/ig,
  887. user_passwd: /(dbpassword|password)$/ig,
  888. db_connection_url: /jdbc\.url|connectionurl/ig,
  889. driver_class: /ConnectionDriverName|jdbc\.driver/ig,
  890. schema_name: /db\.schema\.name/ig
  891. };
  892. }.property(),
  893. /** @property {Object} connectionProperties - service specific config values mapped for custom action request **/
  894. connectionProperties: function() {
  895. var propObj = {};
  896. for (var key in this.get('propertiesPattern')) {
  897. propObj[key] = this.getConnectionProperty(this.get('propertiesPattern')[key]);
  898. }
  899. return propObj;
  900. }.property('propertiesPattern'),
  901. getConnectionProperty: function(regexp) {
  902. var propertyName = this.get('requiredProperties').filter(function(item) {
  903. return regexp.test(item);
  904. })[0];
  905. return this.get('content.serviceProperties')[propertyName];
  906. },
  907. /**
  908. * Properties that stores in local storage used for handling
  909. * last success connection.
  910. *
  911. * @property {Object} preparedDBProperties
  912. **/
  913. preparedDBProperties: function() {
  914. var propObj = {};
  915. for (var key in this.get('propertiesPattern')) {
  916. var propValue = this.getConnectionProperty(this.get('propertiesPattern')[key]);
  917. propObj[key] = propValue;
  918. }
  919. return propObj;
  920. }.property(),
  921. /** @property {object} requiredProperties - properties that necessary for database connection **/
  922. requiredProperties: function() {
  923. var propertiesMap = {
  924. OOZIE: ['oozie.db.schema.name','oozie.service.JPAService.jdbc.username','oozie.service.JPAService.jdbc.password','oozie.service.JPAService.jdbc.driver','oozie.service.JPAService.jdbc.url'],
  925. HIVE: ['ambari.hive.db.schema.name','javax.jdo.option.ConnectionUserName','javax.jdo.option.ConnectionPassword','javax.jdo.option.ConnectionDriverName','javax.jdo.option.ConnectionURL']
  926. };
  927. return propertiesMap[this.get('content.reassign.service_id')];
  928. }.property(),
  929. dbType: function() {
  930. var databaseTypes = /MySQL|PostgreS|Oracle|Derby|MSSQL/gi;
  931. var databaseProp = this.get('content.serviceProperties')[this.get('dbProperty')];
  932. return databaseProp.match(databaseTypes)[0];
  933. }.property('dbProperty'),
  934. prepareDBCheckAction: function() {
  935. var ambariProperties = null;
  936. var properties = this.get('content.serviceProperties');
  937. var params = this.get('preparedDBProperties');
  938. ambariProperties = App.router.get('clusterController.ambariProperties');
  939. params['db_name'] = this.get('dbType');
  940. params['jdk_location'] = ambariProperties['jdk_location'];
  941. params['jdk_name'] = ambariProperties['jdk.name'];
  942. params['java_home'] = ambariProperties['java.home'];
  943. params['threshold'] = 60;
  944. params['ambari_server_host'] = location.hostname;
  945. params['check_execute_list'] = "db_connection_check";
  946. App.ajax.send({
  947. name: 'custom_action.create',
  948. sender: this,
  949. data: {
  950. requestInfo: {
  951. "context": "Check host",
  952. "action": "check_host",
  953. "parameters": params
  954. },
  955. filteredHosts: [this.get('content.reassignHosts.target')]
  956. },
  957. success: 'onCreateActionSuccess',
  958. error: 'onTaskError'
  959. });
  960. },
  961. onCreateActionSuccess: function(data) {
  962. this.set('checkDBRequestId', data.Requests.id);
  963. App.ajax.send({
  964. name: 'custom_action.request',
  965. sender: this,
  966. data: {
  967. requestId: this.get('checkDBRequestId')
  968. },
  969. success: 'setCheckDBTaskId'
  970. });
  971. },
  972. setCheckDBTaskId: function(data) {
  973. this.set('checkDBTaskId', data.items[0].Tasks.id);
  974. this.startDBCheckPolling();
  975. },
  976. startDBCheckPolling: function() {
  977. this.getDBConnTaskInfo();
  978. },
  979. getDBConnTaskInfo: function() {
  980. this.setTaskStatus(this.get('currentTaskId'), 'IN_PROGRESS');
  981. this.get('tasks').findProperty('id', this.get('currentTaskId')).set('progress', 100);
  982. this.set('logs', []);
  983. App.ajax.send({
  984. name: 'custom_action.request',
  985. sender: this,
  986. data: {
  987. requestId: this.get('checkDBRequestId'),
  988. taskId: this.get('checkDBTaskId')
  989. },
  990. success: 'getDBConnTaskInfoSuccess'
  991. });
  992. },
  993. getDBConnTaskInfoSuccess: function(data) {
  994. var task = data.Tasks;
  995. if (task.status === 'COMPLETED') {
  996. var structuredOut = task.structured_out.db_connection_check;
  997. if (structuredOut.exit_code != 0) {
  998. this.showConnectionErrorPopup(structuredOut.message);
  999. this.onTaskError();
  1000. } else {
  1001. this.onTaskCompleted();
  1002. }
  1003. }
  1004. if (task.status === 'FAILED') {
  1005. this.onTaskError();
  1006. }
  1007. if (/PENDING|QUEUED|IN_PROGRESS/.test(task.status)) {
  1008. Em.run.later(this, function() {
  1009. this.startDBCheckPolling();
  1010. }, 3000);
  1011. }
  1012. },
  1013. showConnectionErrorPopup: function(error) {
  1014. var popup = App.showAlertPopup('Database Connection Error');
  1015. popup.set('body', error);
  1016. },
  1017. testDBRetryTooltip: function() {
  1018. var db_host = this.get('content.serviceProperties.database_hostname');
  1019. var db_type = this.get('dbType');
  1020. var db_props = this.get('preparedDBProperties');
  1021. return Em.I18n.t('services.reassign.step4.tasks.testDBConnection.tooltip').format(
  1022. db_host, db_type, db_props['schema_name'], db_props['user_name'],
  1023. db_props['user_passwd'], db_props['driver_class'], db_props['db_connection_url']
  1024. );
  1025. }.property('dbProperties'),
  1026. saveServiceProperties: function(configs) {
  1027. App.router.get(this.get('content.controllerName')).saveServiceProperties(configs);
  1028. }
  1029. });