step4_controller.js 35 KB

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