step4_controller.js 39 KB

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