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