step4_controller.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  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. index = null
  268. cmd = null;
  269. commands.forEach(function(command) {
  270. cmd = tasks.filterProperty('command', command);
  271. if (cmd.length === 0) {
  272. return false;
  273. } else {
  274. index = tasks.indexOf( cmd[0] );
  275. }
  276. tasks.splice( index, 1 );
  277. });
  278. },
  279. /**
  280. * initialize tasks
  281. */
  282. initializeTasks: function () {
  283. var commands = this.get('commands');
  284. var currentStep = App.router.get('reassignMasterController.currentStep');
  285. var hostComponentsNames = this.getHostComponentsNames();
  286. if (this.isComponentWithDB()) {
  287. commands = this.get('commandsForDB');
  288. }
  289. for (var i = 0; i < commands.length; i++) {
  290. var TaskLabel = i === 3 ? this.get('serviceName') : hostComponentsNames; //For Reconfigure task, show serviceName
  291. var title = Em.I18n.t('services.reassign.step4.tasks.' + commands[i] + '.title').format(TaskLabel);
  292. this.get('tasks').pushObject(Ember.Object.create({
  293. title: title,
  294. status: 'PENDING',
  295. id: i,
  296. command: commands[i],
  297. showRetry: false,
  298. showRollback: false,
  299. name: title,
  300. displayName: title,
  301. progress: 0,
  302. isRunning: false,
  303. hosts: []
  304. }));
  305. }
  306. this.removeUnneededTasks();
  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 'WEBHCAT_SERVER':
  439. urlParams.push('(type=webhcat-site&tag=' + data.Clusters.desired_configs['webhcat-site'].tag + ')');
  440. case 'HIVE_SERVER':
  441. urlParams.push('(type=hive-site&tag=' + data.Clusters.desired_configs['hive-site'].tag + ')');
  442. break;
  443. case 'HIVE_METASTORE':
  444. urlParams.push('(type=hive-site&tag=' + data.Clusters.desired_configs['hive-site'].tag + ')');
  445. break;
  446. case 'MYSQL_SERVER':
  447. urlParams.push('(type=hive-site&tag=' + data.Clusters.desired_configs['hive-site'].tag + ')');
  448. break;
  449. }
  450. return urlParams;
  451. },
  452. onLoadConfigsTags: function (data) {
  453. var urlParams = this.getConfigUrlParams(this.get('content.reassign.component_name'), data);
  454. App.ajax.send({
  455. name: 'reassign.load_configs',
  456. sender: this,
  457. data: {
  458. urlParams: urlParams.join('|')
  459. },
  460. success: 'onLoadConfigs',
  461. error: 'onTaskError'
  462. });
  463. },
  464. onLoadConfigs: function (data) {
  465. var componentName = this.get('content.reassign.component_name');
  466. var targetHostName = this.get('content.reassignHosts.target');
  467. var configs = {};
  468. var secureConfigs = [];
  469. data.items.forEach(function (item) {
  470. configs[item.type] = item.properties;
  471. }, this);
  472. this.setAdditionalConfigs(configs, componentName, targetHostName);
  473. this.setSecureConfigs(secureConfigs, configs, componentName);
  474. if (componentName === 'NAMENODE') {
  475. this.setSpecificNamenodeConfigs(configs, targetHostName);
  476. }
  477. if (componentName === 'RESOURCEMANAGER') {
  478. this.setSpecificResourceMangerConfigs(configs, targetHostName);
  479. }
  480. this.saveClusterStatus(secureConfigs, this.getComponentDir(configs, componentName));
  481. this.saveConfigsToServer(configs);
  482. this.saveServiceProperties(configs);
  483. },
  484. /**
  485. * make PUT call to save configs to server
  486. * @param configs
  487. */
  488. saveConfigsToServer: function (configs) {
  489. App.ajax.send({
  490. name: 'common.across.services.configurations',
  491. sender: this,
  492. data: {
  493. data: '[' + this.getServiceConfigData(configs).toString() + ']'
  494. },
  495. success: 'onSaveConfigs',
  496. error: 'onTaskError'
  497. });
  498. },
  499. /**
  500. * gather and format config data before sending to server
  501. * @param configs
  502. * @return {Array}
  503. * @method getServiceConfigData
  504. */
  505. getServiceConfigData: function (configs) {
  506. var componentName = this.get('content.reassign.component_name');
  507. var tagName = 'version' + (new Date).getTime();
  508. var configData = Object.keys(configs).map(function (_siteName) {
  509. return {
  510. type: _siteName,
  511. tag: tagName,
  512. properties: configs[_siteName],
  513. service_config_version_note: Em.I18n.t('services.reassign.step4.save.configuration.note').format(App.format.role(componentName))
  514. }
  515. });
  516. var allConfigData = [];
  517. App.Service.find().forEach(function (service) {
  518. var stackService = App.StackService.find().findProperty('serviceName', service.get('serviceName'));
  519. if (stackService) {
  520. var serviceConfigData = [];
  521. Object.keys(stackService.get('configTypesRendered')).forEach(function (type) {
  522. var serviceConfigTag = configData.findProperty('type', type);
  523. if (serviceConfigTag) {
  524. serviceConfigData.pushObject(serviceConfigTag);
  525. }
  526. }, this);
  527. allConfigData.pushObject(JSON.stringify({
  528. Clusters: {
  529. desired_config: serviceConfigData
  530. }
  531. }));
  532. }
  533. }, this);
  534. return allConfigData;
  535. },
  536. /**
  537. * set specific configs which applies only to NameNode component
  538. * @param configs
  539. * @param targetHostName
  540. */
  541. setSpecificNamenodeConfigs: function (configs, targetHostName) {
  542. var sourceHostName = this.get('content.reassignHosts.source');
  543. if (App.get('isHaEnabled')) {
  544. var nameServices = configs['hdfs-site']['dfs.nameservices'];
  545. var suffix = (configs['hdfs-site']['dfs.namenode.http-address.' + nameServices + '.nn1'] === sourceHostName + ':50070') ? '.nn1' : '.nn2';
  546. configs['hdfs-site']['dfs.namenode.http-address.' + nameServices + suffix] = targetHostName + ':50070';
  547. configs['hdfs-site']['dfs.namenode.https-address.' + nameServices + suffix] = targetHostName + ':50470';
  548. configs['hdfs-site']['dfs.namenode.rpc-address.' + nameServices + suffix] = targetHostName + ':8020';
  549. }
  550. if (!App.get('isHaEnabled') && App.Service.find('HBASE').get('isLoaded')) {
  551. configs['hbase-site']['hbase.rootdir'] = configs['hbase-site']['hbase.rootdir'].replace(/\/\/[^\/]*/, '//' + targetHostName + ':8020');
  552. }
  553. },
  554. /**
  555. * set specific configs which applies only to ResourceManager component
  556. * @param configs
  557. * @param targetHostName
  558. */
  559. setSpecificResourceMangerConfigs: function (configs, targetHostName) {
  560. var sourceHostName = this.get('content.reassignHosts.source');
  561. if (App.get('isRMHaEnabled')) {
  562. if (configs['yarn-site']['yarn.resourcemanager.hostname.rm1'] === sourceHostName) {
  563. configs['yarn-site']['yarn.resourcemanager.hostname.rm1'] = targetHostName;
  564. } else {
  565. configs['yarn-site']['yarn.resourcemanager.hostname.rm2'] = targetHostName;
  566. }
  567. }
  568. },
  569. /**
  570. * set secure configs for component
  571. * @param secureConfigs
  572. * @param configs
  573. * @param componentName
  574. * @return {Boolean}
  575. */
  576. setSecureConfigs: function (secureConfigs, configs, componentName) {
  577. var securityEnabled = this.get('content.securityEnabled');
  578. var component = this.get('secureConfigsMap').findProperty('componentName', componentName);
  579. if (Em.isNone(component) || !securityEnabled) return false;
  580. component.configs.forEach(function (config) {
  581. secureConfigs.push({
  582. keytab: configs[config.site][config.keytab],
  583. principal: configs[config.site][config.principal]
  584. });
  585. });
  586. return true;
  587. },
  588. /**
  589. * derive component directory from configurations
  590. * @param configs
  591. * @param componentName
  592. * @return {String}
  593. */
  594. getComponentDir: function (configs, componentName) {
  595. if (componentName === 'NAMENODE') {
  596. return configs['hdfs-site']['dfs.namenode.name.dir'];
  597. } else if (componentName === 'SECONDARY_NAMENODE') {
  598. return configs['hdfs-site']['dfs.namenode.checkpoint.dir'];
  599. }
  600. return '';
  601. },
  602. /**
  603. * save cluster status to server
  604. *
  605. * @param secureConfigs
  606. * @param componentDir
  607. * @return {Boolean}
  608. */
  609. saveClusterStatus: function (secureConfigs, componentDir) {
  610. if (componentDir || secureConfigs.length) {
  611. App.router.get(this.get('content.controllerName')).saveComponentDir(componentDir);
  612. App.router.get(this.get('content.controllerName')).saveSecureConfigs(secureConfigs);
  613. App.clusterStatus.setClusterStatus({
  614. clusterName: this.get('content.cluster.name'),
  615. clusterState: this.get('clusterDeployState'),
  616. wizardControllerName: this.get('content.controllerName'),
  617. localdb: App.db.data
  618. });
  619. return true;
  620. }
  621. return false;
  622. },
  623. onSaveConfigs: function () {
  624. this.onTaskCompleted();
  625. },
  626. startZooKeeperServers: function () {
  627. var components = this.get('content.masterComponentHosts').filterProperty('component', 'ZOOKEEPER_SERVER');
  628. this.updateComponent('ZOOKEEPER_SERVER', components.mapProperty('hostName'), "ZOOKEEPER", "Start");
  629. },
  630. startNameNode: function () {
  631. var components = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE');
  632. this.updateComponent('NAMENODE', components.mapProperty('hostName').without(this.get('content.reassignHosts.source')), "HDFS", "Start");
  633. },
  634. /**
  635. * make server call to start services
  636. */
  637. startServices: function () {
  638. App.ajax.send({
  639. name: 'common.services.update',
  640. sender: this,
  641. data: this.getStartServicesData(),
  642. success: 'startPolling',
  643. error: 'onTaskError'
  644. });
  645. },
  646. /**
  647. * compute data for call to start services
  648. * @return {Object}
  649. */
  650. getStartServicesData: function () {
  651. var unrelatedServices = this.get('unrelatedServicesMap')[this.get('content.reassign.component_name')];
  652. var data = {};
  653. if (unrelatedServices) {
  654. var list = App.Service.find().mapProperty("serviceName").filter(function (s) {
  655. return !unrelatedServices.contains(s)
  656. }).join(',');
  657. data = {
  658. "context": "Start required services",
  659. "ServiceInfo": {
  660. "state": "STARTED"
  661. },
  662. "urlParams": "ServiceInfo/service_name.in(" + list + ")"
  663. };
  664. } else {
  665. data = {
  666. "context": "Start all services",
  667. "ServiceInfo": {
  668. "state": "STARTED"
  669. },
  670. "urlParams": "params/run_smoke_test=true"
  671. };
  672. }
  673. return data;
  674. },
  675. /**
  676. * make DELETE call for each host component on host
  677. */
  678. deleteHostComponents: function () {
  679. this.set('multiTaskCounter', 0);
  680. var hostComponents = this.get('hostComponents');
  681. var hostName = this.get('content.reassignHosts.source');
  682. for (var i = 0; i < hostComponents.length; i++) {
  683. App.ajax.send({
  684. name: 'common.delete.host_component',
  685. sender: this,
  686. data: {
  687. hostName: hostName,
  688. componentName: hostComponents[i]
  689. },
  690. success: 'onComponentsTasksSuccess',
  691. error: 'onDeleteHostComponentsError'
  692. });
  693. }
  694. },
  695. onDeleteHostComponentsError: function (error) {
  696. if (error.responseText.indexOf('org.apache.ambari.server.controller.spi.NoSuchResourceException') !== -1) {
  697. this.onComponentsTasksSuccess();
  698. } else {
  699. this.onTaskError();
  700. }
  701. },
  702. done: function () {
  703. if (!this.get('isSubmitDisabled')) {
  704. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  705. if (this.get('content.hasManualSteps')) {
  706. App.router.send('next');
  707. } else {
  708. App.router.send('complete');
  709. }
  710. }
  711. },
  712. /**
  713. * make server call to clean MYSQL
  714. */
  715. cleanMySqlServer: function () {
  716. var hostname = App.HostComponent.find().filterProperty('componentName', 'MYSQL_SERVER').get('firstObject.hostName');
  717. if (this.get('content.reassign.component_name') === 'MYSQL_SERVER') {
  718. hostname = this.get('content.reassignHosts.target');
  719. }
  720. App.ajax.send({
  721. name: 'service.mysql.clean',
  722. sender: this,
  723. data: {
  724. host: hostname
  725. },
  726. success: 'startPolling',
  727. error: 'onTaskError'
  728. });
  729. },
  730. /**
  731. * make server call to configure MYSQL
  732. */
  733. configureMySqlServer : function () {
  734. var hostname = App.HostComponent.find().filterProperty('componentName', 'MYSQL_SERVER').get('firstObject.hostName');
  735. if (this.get('content.reassign.component_name') === 'MYSQL_SERVER') {
  736. hostname = this.get('content.reassignHosts.target');
  737. }
  738. App.ajax.send({
  739. name: 'service.mysql.configure',
  740. sender: this,
  741. data: {
  742. host: hostname
  743. },
  744. success: 'startPolling',
  745. error: 'onTaskError'
  746. });
  747. },
  748. startMySqlServer: function() {
  749. App.ajax.send({
  750. name: 'common.host.host_component.update',
  751. sender: this,
  752. data: {
  753. context: "Start MySQL Server",
  754. hostName: App.HostComponent.find().filterProperty('componentName', 'MYSQL_SERVER').get('firstObject.hostName'),
  755. serviceName: "HIVE",
  756. componentName: "MYSQL_SERVER",
  757. HostRoles: {
  758. state: "STARTED"
  759. }
  760. },
  761. success: 'startPolling',
  762. error: 'onTaskError'
  763. });
  764. },
  765. startNewMySqlServer: function() {
  766. App.ajax.send({
  767. name: 'common.host.host_component.update',
  768. sender: this,
  769. data: {
  770. context: "Start MySQL Server",
  771. hostName: this.get('content.reassignHosts.target'),
  772. serviceName: "HIVE",
  773. componentName: "MYSQL_SERVER",
  774. HostRoles: {
  775. state: "STARTED"
  776. }
  777. },
  778. success: 'startPolling',
  779. error: 'onTaskError'
  780. });
  781. },
  782. testDBConnection: function() {
  783. this.prepareDBCheckAction();
  784. // this.onTaskCompleted();
  785. },
  786. isComponentWithDB: function() {
  787. return ['HIVE_SERVER', 'HIVE_METASTORE', 'OOZIE_SERVER'].contains(this.get('content.reassign.component_name'));
  788. },
  789. dbProperty: function() {
  790. var componentName = this.get('content.reassign.component_name');
  791. var property = null;
  792. switch(componentName) {
  793. case 'HIVE_SERVER':
  794. case 'HIVE_METASTORE':
  795. property = 'javax.jdo.option.ConnectionDriverName';
  796. break;
  797. case 'OOZIE_SERVER':
  798. property = 'oozie.service.JPAService.jdbc.url';
  799. break;
  800. }
  801. return property;
  802. }.property(),
  803. /** @property {Object} propertiesPattern - check pattern according to type of connection properties **/
  804. propertiesPattern: function() {
  805. return {
  806. user_name: /(username|dblogin)$/ig,
  807. user_passwd: /(dbpassword|password)$/ig,
  808. db_connection_url: /jdbc\.url|connectionurl/ig,
  809. driver_class: /ConnectionDriverName|jdbc\.driver/ig,
  810. schema_name: /db\.schema\.name/ig
  811. };
  812. }.property(),
  813. /** @property {Object} connectionProperties - service specific config values mapped for custom action request **/
  814. connectionProperties: function() {
  815. var propObj = {};
  816. for (var key in this.get('propertiesPattern')) {
  817. propObj[key] = this.getConnectionProperty(this.get('propertiesPattern')[key]);
  818. }
  819. return propObj;
  820. }.property('propertiesPattern'),
  821. getConnectionProperty: function(regexp) {
  822. var propertyName = this.get('requiredProperties').filter(function(item) {
  823. return regexp.test(item);
  824. })[0];
  825. return this.get('content.serviceProperties')[propertyName];
  826. },
  827. /**
  828. * Properties that stores in local storage used for handling
  829. * last success connection.
  830. *
  831. * @property {Object} preparedDBProperties
  832. **/
  833. preparedDBProperties: function() {
  834. var propObj = {};
  835. for (var key in this.get('propertiesPattern')) {
  836. var propValue = this.getConnectionProperty(this.get('propertiesPattern')[key]);
  837. propObj[key] = propValue;
  838. }
  839. return propObj;
  840. }.property(),
  841. /** @property {object} requiredProperties - properties that necessary for database connection **/
  842. requiredProperties: function() {
  843. var propertiesMap = {
  844. 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'],
  845. HIVE: ['ambari.hive.db.schema.name','javax.jdo.option.ConnectionUserName','javax.jdo.option.ConnectionPassword','javax.jdo.option.ConnectionDriverName','javax.jdo.option.ConnectionURL']
  846. };
  847. return propertiesMap[this.get('content.reassign.service_id')];
  848. }.property(),
  849. dbType: function() {
  850. var databaseTypes = /MySQL|PostgreS|Oracle|Derby|MSSQL/gi;
  851. var databaseProp = this.get('content.serviceProperties')[this.get('dbProperty')];
  852. return databaseProp.match(databaseTypes)[0];
  853. }.property('dbProperty'),
  854. prepareDBCheckAction: function() {
  855. var ambariProperties = null;
  856. var properties = this.get('content.serviceProperties');
  857. var params = this.get('preparedDBProperties');
  858. ambariProperties = App.router.get('clusterController.ambariProperties');
  859. params['db_name'] = this.get('dbType');
  860. params['jdk_location'] = ambariProperties['jdk_location'];
  861. params['jdk_name'] = ambariProperties['jdk.name'];
  862. params['java_home'] = ambariProperties['java.home'];
  863. params['threshold'] = 60;
  864. params['ambari_server_host'] = location.hostname;
  865. params['check_execute_list'] = "db_connection_check";
  866. App.ajax.send({
  867. name: 'custom_action.create',
  868. sender: this,
  869. data: {
  870. requestInfo: {
  871. "context": "Check host",
  872. "action": "check_host",
  873. "parameters": params
  874. },
  875. filteredHosts: [this.get('content.reassignHosts.target')]
  876. },
  877. success: 'onCreateActionSuccess',
  878. error: 'onTaskError'
  879. });
  880. },
  881. onCreateActionSuccess: function(data) {
  882. this.set('checkDBRequestId', data.Requests.id);
  883. App.ajax.send({
  884. name: 'custom_action.request',
  885. sender: this,
  886. data: {
  887. requestId: this.get('checkDBRequestId')
  888. },
  889. success: 'setCheckDBTaskId'
  890. });
  891. },
  892. setCheckDBTaskId: function(data) {
  893. this.set('checkDBTaskId', data.items[0].Tasks.id);
  894. this.startDBCheckPolling();
  895. },
  896. startDBCheckPolling: function() {
  897. this.getDBConnTaskInfo();
  898. },
  899. getDBConnTaskInfo: function() {
  900. this.setTaskStatus(this.get('currentTaskId'), 'IN_PROGRESS');
  901. this.get('tasks').findProperty('id', this.get('currentTaskId')).set('progress', 100);
  902. this.set('logs', []);
  903. App.ajax.send({
  904. name: 'custom_action.request',
  905. sender: this,
  906. data: {
  907. requestId: this.get('checkDBRequestId'),
  908. taskId: this.get('checkDBTaskId')
  909. },
  910. success: 'getDBConnTaskInfoSuccess'
  911. });
  912. },
  913. getDBConnTaskInfoSuccess: function(data) {
  914. var task = data.Tasks;
  915. if (task.status === 'COMPLETED') {
  916. var structuredOut = task.structured_out.db_connection_check;
  917. if (structuredOut.exit_code != 0) {
  918. this.showConnectionErrorPopup(structuredOut.message);
  919. this.onTaskError();
  920. } else {
  921. this.onTaskCompleted();
  922. }
  923. }
  924. if (task.status === 'FAILED') {
  925. this.onTaskError();
  926. }
  927. if (/PENDING|QUEUED|IN_PROGRESS/.test(task.status)) {
  928. Em.run.later(this, function() {
  929. this.startDBCheckPolling();
  930. }, 3000);
  931. }
  932. },
  933. showConnectionErrorPopup: function(error) {
  934. var popup = App.showAlertPopup('Database Connection Error');
  935. popup.set('body', error);
  936. },
  937. testDBRetryTooltip: function() {
  938. var db_host = this.get('content.serviceProperties.database_hostname');
  939. var db_type = this.get('dbType');
  940. var db_props = this.get('preparedDBProperties');
  941. return Em.I18n.t('services.reassign.step4.tasks.testDBConnection.tooltip').format(
  942. db_host, db_type, db_props['schema_name'], db_props['user_name'],
  943. db_props['user_passwd'], db_props['driver_class'], db_props['db_connection_url']
  944. );
  945. }.property('dbProperties'),
  946. saveServiceProperties: function(configs) {
  947. App.router.get(this.get('content.controllerName')).saveServiceProperties(configs);
  948. }
  949. });