step4_controller.js 39 KB

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