step4_controller.js 37 KB

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