step4_controller.js 36 KB

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