step4_controller.js 34 KB

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