step4_controller.js 33 KB

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