step4_controller.js 35 KB

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