step4_controller.js 33 KB

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