rollback_controller.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. require('controllers/main/admin/highAvailability/progress_controller');
  20. App.HighAvailabilityRollbackController = App.HighAvailabilityProgressPageController.extend({
  21. name: "highAvailabilityRollbackController",
  22. failedTask: null,
  23. configsSaved: false,
  24. deletedHdfsClients: 0,
  25. numOfDelOperations: 0,
  26. isRollback: true,
  27. hostsToPerformDel: [],
  28. commands: [
  29. 'stopAllServices',
  30. 'restoreHBaseConfigs',
  31. 'stopFailoverControllers',
  32. 'deleteFailoverControllers',
  33. 'stopStandbyNameNode',
  34. 'stopNameNode',
  35. 'restoreHDFSConfigs',
  36. 'enableSecondaryNameNode',
  37. 'stopJournalNodes',
  38. 'deleteJournalNodes',
  39. 'deleteAdditionalNameNode',
  40. 'startAllServices'
  41. ],
  42. loadStep: function () {
  43. this.initData();
  44. this.clearStep();
  45. this.loadTasks();
  46. this.addObserver('tasks.@each.status', this, 'onTaskStatusChange');
  47. this.onTaskStatusChange();
  48. },
  49. initData: function () {
  50. this.loadMasterComponentHosts();
  51. this.loadFailedTask();
  52. this.loadHdfsClientHosts();
  53. },
  54. setCommandsAndTasks: function(tmpTasks) {
  55. var fTask = this.get('failedTask');
  56. var newCommands = [];
  57. var newTasks = [];
  58. var index = [
  59. 'deleteSNameNode',
  60. 'startAllServices',
  61. 'reconfigureHBase',
  62. 'startZKFC',
  63. 'installZKFC',
  64. 'startSecondNameNode',
  65. 'startNameNode',
  66. 'startZooKeeperServers',
  67. 'reconfigureHDFS',
  68. 'disableSNameNode',
  69. 'startJournalNodes',
  70. 'installJournalNodes',
  71. 'installNameNode',
  72. 'stopAllServices'
  73. ].indexOf(fTask.command);
  74. if(index > 6){
  75. --index;
  76. }
  77. newCommands = this.get('commands').splice(index);
  78. this.set('commands', newCommands);
  79. newTasks = tmpTasks.splice(index);
  80. for (var i = 0; i < newTasks.length; i++) {
  81. newTasks[i].id = i;
  82. };
  83. this.set('tasks', newTasks);
  84. var hbaseTask = this.get('tasks').findProperty('command', 'restoreHBaseConfigs');
  85. if (!App.Service.find().someProperty('serviceName', 'HBASE') && hbaseTask) {
  86. this.get('tasks').splice(hbaseTask.get('id'), 1);
  87. }
  88. },
  89. clearStep: function () {
  90. this.set('isSubmitDisabled', true);
  91. this.set('tasks', []);
  92. this.set('logs', []);
  93. this.set('currentRequestIds', []);
  94. var commands = this.get('commands');
  95. var tmpTasks = [];
  96. for (var i = 0; i < commands.length; i++) {
  97. tmpTasks.pushObject(Ember.Object.create({
  98. title: Em.I18n.t('admin.highAvailability.rollback.task' + i + '.title'),
  99. status: 'PENDING',
  100. id: i,
  101. command: commands[i],
  102. showRetry: false,
  103. showRollback: false,
  104. showSkip: false,
  105. name: Em.I18n.t('admin.highAvailability.rollback.task' + i + '.title'),
  106. displayName: Em.I18n.t('admin.highAvailability.rollback.task' + i + '.title'),
  107. progress: 0,
  108. isRunning: false,
  109. hosts: []
  110. }));
  111. }
  112. this.setCommandsAndTasks(tmpTasks);
  113. },
  114. onTaskStatusChange: function () {
  115. if (!this.get('tasks').someProperty('status', 'IN_PROGRESS') && !this.get('tasks').someProperty('status', 'QUEUED') && !this.get('tasks').someProperty('status', 'FAILED')) {
  116. var nextTask = this.get('tasks').findProperty('status', 'PENDING');
  117. if (nextTask) {
  118. this.set('status', 'IN_PROGRESS');
  119. this.runTask(nextTask.get('id'));
  120. this.setTaskStatus(nextTask.get('id'), 'QUEUED');
  121. this.set('currentTaskId', nextTask.get('id'));
  122. } else {
  123. this.set('status', 'COMPLETED');
  124. this.set('isSubmitDisabled', false);
  125. }
  126. } else if (this.get('tasks').someProperty('status', 'FAILED')) {
  127. this.set('status', 'FAILED');
  128. this.get('tasks').findProperty('status', 'FAILED').set('showRetry', true);
  129. this.get('tasks').findProperty('status', 'FAILED').set('showSkip', true);
  130. }
  131. var statuses = this.get('tasks').mapProperty('status');
  132. var logs = this.get('tasks').mapProperty('hosts');
  133. var requestIds = this.get('currentRequestIds');
  134. this.saveTasksStatuses(statuses);
  135. this.saveRequestIds(requestIds);
  136. this.saveLogs(logs);
  137. App.clusterStatus.setClusterStatus({
  138. clusterName: this.get('content.cluster.name'),
  139. clusterState: 'HIGH_AVAILABILITY_ROLLBACK',
  140. wizardControllerName: 'highAvailabilityRollbackController',
  141. localdb: App.db.data
  142. });
  143. },
  144. skipTask: function () {
  145. var task = this.get('tasks').findProperty('status', 'FAILED');
  146. task.set('showRetry', false);
  147. task.set('showSkip', false);
  148. task.set('status', 'COMPLETED');
  149. },
  150. retryTask: function () {
  151. var task = this.get('tasks').findProperty('status', 'FAILED');
  152. task.set('showRetry', false);
  153. task.set('showSkip', false);
  154. task.set('status', 'PENDING');
  155. },
  156. onTaskCompleted: function () {
  157. var curTaskStatus = this.getTaskStatus(this.get('currentTaskId'));
  158. if (curTaskStatus != 'FAILED' && curTaskStatus != 'TIMEDOUT' && curTaskStatus != 'ABORTED') {
  159. this.setTaskStatus(this.get('currentTaskId'), 'COMPLETED');
  160. }
  161. },
  162. getTaskStatus: function (taskId) {
  163. return this.get('tasks').findProperty('id', taskId).get('status');
  164. },
  165. loadFailedTask: function(){
  166. var failedTask = App.db.getHighAvailabilityWizardFailedTask();
  167. this.set('failedTask', failedTask);
  168. },
  169. done: function () {
  170. if (!this.get('isSubmitDisabled')) {
  171. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  172. this.popup.proceedOnClose();
  173. }
  174. },
  175. stopAllServices: function(){
  176. App.ajax.send({
  177. name: 'admin.high_availability.stop_all_services',
  178. sender: this,
  179. success: 'startPolling',
  180. error: 'onTaskError'
  181. });
  182. },
  183. restoreHBaseConfigs: function(){
  184. this.loadConfigTag("hbaseSiteTag");
  185. var hbaseSiteTag = this.get("content.hbaseSiteTag");
  186. App.ajax.send({
  187. name: 'admin.high_availability.load_hbase_configs',
  188. sender: this,
  189. data: {
  190. hbaseSiteTag: hbaseSiteTag
  191. },
  192. success: 'onLoadHbaseConfigs',
  193. error: 'onTaskError'
  194. });
  195. },
  196. stopFailoverControllers: function(){
  197. var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName');
  198. this.stopComponent('ZKFC', hostNames);
  199. },
  200. deleteFailoverControllers: function(){
  201. var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName');
  202. this.checkBeforeDelete('ZKFC', hostNames);
  203. },
  204. stopStandbyNameNode: function(){
  205. var hostName = this.get('content.masterComponentHosts').findProperty('isAddNameNode', true).hostName;;
  206. this.stopComponent('NAMENODE', hostName);
  207. },
  208. stopNameNode: function(){
  209. var hostNames = this.get('content.masterComponentHosts').findProperty('isCurNameNode').hostName;
  210. this.stopComponent('NAMENODE', hostNames);
  211. },
  212. restoreHDFSConfigs: function(){
  213. this.unInstallHDFSClients();
  214. },
  215. enableSecondaryNameNode: function(){
  216. var hostName = this.get('content.masterComponentHosts').findProperty('component', 'SECONDARY_NAMENODE').hostName;
  217. this.installComponent('SECONDARY_NAMENODE', hostName, hostName.length);
  218. },
  219. stopJournalNodes: function(){
  220. var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'JOURNALNODE').mapProperty('hostName');
  221. this.stopComponent('JOURNALNODE', hostNames);
  222. },
  223. deleteJournalNodes: function(){
  224. var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'JOURNALNODE').mapProperty('hostName');
  225. this.unInstallComponent('JOURNALNODE', hostNames);
  226. },
  227. deleteAdditionalNameNode: function(){
  228. var hostNames = this.get('content.masterComponentHosts').filterProperty('isAddNameNode', true).mapProperty('hostName');
  229. this.unInstallComponent('NAMENODE', hostNames);
  230. },
  231. startAllServices: function(){
  232. App.ajax.send({
  233. name: 'admin.high_availability.start_all_services',
  234. sender: this,
  235. success: 'startPolling',
  236. error: 'onTaskError'
  237. });
  238. },
  239. onLoadHbaseConfigs: function (data) {
  240. var hbaseSiteProperties = data.items.findProperty('type', 'hbase-site').properties;
  241. App.ajax.send({
  242. name: 'admin.high_availability.save_configs',
  243. sender: this,
  244. data: {
  245. siteName: 'hbase-site',
  246. properties: hbaseSiteProperties
  247. },
  248. success: 'onTaskCompleted',
  249. error: 'onTaskError'
  250. });
  251. },
  252. stopComponent: function (componentName, hostName) {
  253. if (!(hostName instanceof Array)) {
  254. hostName = [hostName];
  255. }
  256. for (var i = 0; i < hostName.length; i++) {
  257. App.ajax.send({
  258. name: 'admin.high_availability.stop_component',
  259. sender: this,
  260. data: {
  261. hostName: hostName[i],
  262. componentName: componentName,
  263. displayName: App.format.role(componentName),
  264. taskNum: hostName.length
  265. },
  266. success: 'startPolling',
  267. error: 'onTaskError'
  268. });
  269. }
  270. },
  271. onDeletedHDFSClient: function () {
  272. var deletedHdfsClients = this.get('deletedHdfsClients');
  273. var hostName = this.get("content.hdfsClientHostNames");
  274. var notDeletedHdfsClients = hostName.length - deletedHdfsClients;
  275. if (notDeletedHdfsClients > 1 && hostName.length != 1 ) {
  276. this.set('deletedHdfsClients', deletedHdfsClients+1);
  277. return;
  278. }
  279. this.loadConfigTag("hdfsSiteTag");
  280. this.loadConfigTag("coreSiteTag");
  281. var hdfsSiteTag = this.get("content.hdfsSiteTag");
  282. var coreSiteTag = this.get("content.coreSiteTag");
  283. App.ajax.send({
  284. name: 'admin.high_availability.load_configs',
  285. sender: this,
  286. data: {
  287. hdfsSiteTag: hdfsSiteTag,
  288. coreSiteTag: coreSiteTag
  289. },
  290. success: 'onLoadConfigs',
  291. error: 'onTaskError'
  292. });
  293. },
  294. onLoadConfigs: function (data) {
  295. this.set('configsSaved', false);
  296. App.ajax.send({
  297. name: 'admin.high_availability.save_configs',
  298. sender: this,
  299. data: {
  300. siteName: 'hdfs-site',
  301. properties: data.items.findProperty('type', 'hdfs-site').properties
  302. },
  303. success: 'onHdfsConfigsSaved',
  304. error: 'onTaskError'
  305. });
  306. App.ajax.send({
  307. name: 'admin.high_availability.save_configs',
  308. sender: this,
  309. data: {
  310. siteName: 'core-site',
  311. properties: data.items.findProperty('type', 'core-site').properties
  312. },
  313. success: 'onHdfsConfigsSaved',
  314. error: 'onTaskError'
  315. });
  316. },
  317. onHdfsConfigsSaved: function () {
  318. if (!this.get('configsSaved')) {
  319. this.set('configsSaved', true);
  320. return;
  321. }
  322. this.onTaskCompleted();
  323. },
  324. unInstallHDFSClients: function () {
  325. var hostName = this.get("content.hdfsClientHostNames");
  326. for (var i = 0; i < hostName.length; i++) {
  327. App.ajax.send({
  328. name: 'admin.high_availability.delete_component',
  329. sender: this,
  330. data: {
  331. componentName: 'HDFS_CLIENT',
  332. hostName: hostName[i]
  333. },
  334. success: 'onDeletedHDFSClient',
  335. error: 'onTaskError'
  336. });
  337. }
  338. },
  339. unInstallComponent: function (componentName, hostName) {
  340. if (!(hostName instanceof Array)) {
  341. hostName = [hostName];
  342. }
  343. for (var i = 0; i < hostName.length; i++) {
  344. App.ajax.send({
  345. name: 'admin.high_availability.maintenance_mode',
  346. sender: this,
  347. data: {
  348. hostName: hostName[i],
  349. componentName: componentName,
  350. taskNum: hostName.length,
  351. callback: 'checkBeforeDelete'
  352. },
  353. success: 'checkResult',
  354. error: 'checkResult'
  355. });
  356. }
  357. },
  358. checkBeforeDelete: function (componentName, hostName){
  359. this.set('hostsToPerformDel', []);
  360. if (!(hostName instanceof Array)) {
  361. hostName = [hostName];
  362. }
  363. for (var i = 0; i < hostName.length; i++) {
  364. App.ajax.send({
  365. name: 'admin.high_availability.getHostComponent',
  366. sender: this,
  367. data: {
  368. componentName: componentName,
  369. hostName: hostName[i],
  370. taskNum: hostName.length,
  371. callback: 'deleteComponent'
  372. },
  373. success: 'checkResult',
  374. error: 'checkResult'
  375. });
  376. }
  377. },
  378. checkResult: function () {
  379. var callback = arguments[2].callback;
  380. var hostName = arguments[2].hostName;
  381. var componentName = arguments[2].componentName;
  382. var taskNum = arguments[2].taskNum;
  383. var hostsToPerformDel = this.get('hostsToPerformDel');
  384. if(arguments[1] != 'error'){
  385. hostsToPerformDel.push({
  386. hostName: hostName,
  387. isOnHost: true
  388. });
  389. }else{
  390. hostsToPerformDel.push({
  391. hostName: 'error',
  392. isOnHost: false
  393. });
  394. }
  395. if(hostsToPerformDel.length == taskNum){
  396. var hostsForDel = hostsToPerformDel.filterProperty('isOnHost', true).mapProperty('hostName');
  397. this.set('hostsToPerformDel', []);
  398. if(hostsForDel.length == 0){
  399. this.onTaskCompleted();
  400. return;
  401. }
  402. this[callback](componentName, hostsForDel);
  403. }
  404. },
  405. deleteComponent: function (componentName, hostName) {
  406. if (!(hostName instanceof Array)) {
  407. hostName = [hostName];
  408. }
  409. this.set('numOfDelOperations', hostName.length);
  410. for (var i = 0; i < hostName.length; i++) {
  411. App.ajax.send({
  412. name: 'admin.high_availability.delete_component',
  413. sender: this,
  414. data: {
  415. componentName: componentName,
  416. hostName: hostName[i]
  417. },
  418. success: 'onDeleteComplete',
  419. error: 'onTaskError'
  420. });
  421. }
  422. },
  423. onDeleteComplete: function () {
  424. var leftOp = this.get('numOfDelOperations');
  425. if(leftOp > 1){
  426. this.set('numOfDelOperations', leftOp-1);
  427. return;
  428. }
  429. this.onTaskCompleted();
  430. }
  431. });