step4_controller.js 38 KB

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