Browse Source

AMBARI-8914. NameNode HA wizard -> Create Checkpoint page: Next button is disabled and incorrect error message is shown by the UI (onechiporenko)

Oleg Nechiporenko 10 years ago
parent
commit
8413cb3e9d

+ 1 - 0
ambari-web/app/assets/test/tests.js

@@ -59,6 +59,7 @@ var files = ['test/init_model_test',
   'test/controllers/main/admin/serviceAccounts_controller_test',
   'test/controllers/main/admin/highAvailability_controller_test',
   'test/controllers/main/admin/highAvailability/progress_controller_test',
+  'test/controllers/main/admin/highAvailability/nameNode/step4_controller_test',
   'test/controllers/main/admin/security_test',
   'test/controllers/main/admin/security/disable_test',
   'test/controllers/main/admin/security/security_progress_controller_test',

+ 13 - 16
ambari-web/app/controllers/main/admin/highAvailability/nameNode/step4_controller.js

@@ -43,23 +43,20 @@ App.HighAvailabilityWizardStep4Controller = Em.Controller.extend({
   },
 
   checkNnCheckPointStatus: function (data) {
-    if (data.HostRoles.desired_state === 'STARTED') {
-      this.set('isNameNodeStarted', true);
-      var self = this;
-      var journalTransactionInfo = $.parseJSON(data.metrics.dfs.namenode.JournalTransactionInfo);
-      var isInSafeMode = (data.metrics.dfs.namenode.Safemode != "");
-      journalTransactionInfo = parseInt(journalTransactionInfo.LastAppliedOrWrittenTxId) - parseInt(journalTransactionInfo.MostRecentCheckpointTxId);
-      if (journalTransactionInfo <= 1 && isInSafeMode) {
-        this.set("isNextEnabled", true);
-        return;
-      }
-
-      window.setTimeout(function () {
-        self.pullCheckPointStatus()
-      }, self.POLL_INTERVAL);
-    } else {
-      this.set('isNameNodeStarted', false);
+    this.set('isNameNodeStarted', data.HostRoles.desired_state === 'STARTED');
+    var self = this;
+    var journalTransactionInfo = $.parseJSON(Em.get(data, 'metrics.dfs.namenode.JournalNodeTransactionInfo'));
+    var isInSafeMode = !Em.isEmpty(Em.get(data, 'metrics.dfs.namenode.Safemode'));
+    // in case when transaction info absent or invalid return 2 which will return false in next `if` statement
+    journalTransactionInfo = !!journalTransactionInfo ? (parseInt(journalTransactionInfo.LastAppliedOrWrittenTxId) - parseInt(journalTransactionInfo.MostRecentCheckpointTxId)) : 2;
+    if (journalTransactionInfo <= 1 && isInSafeMode) {
+      this.set("isNextEnabled", true);
+      return;
     }
+    
+    window.setTimeout(function () {
+      self.pullCheckPointStatus();
+    }, self.POLL_INTERVAL);
   },
 
   done: function () {

+ 1 - 1
ambari-web/app/messages.js

@@ -1015,7 +1015,7 @@ Em.I18n.translations = {
   'admin.highAvailability.wizard.step2.header':'Select Hosts',
   'admin.highAvailability.wizard.step3.header':'Review',
   'admin.highAvailability.wizard.step4.header':'Create Checkpoint',
-  'admin.highAvailability.wizard.step4.error.nameNode':'NameNode is not started. Please quit wizard and start NameNode first.',
+  'admin.highAvailability.wizard.step4.error.nameNode':'NameNode is in the process of being stopped. Please make sure that namenode is running to create checkpoint successfully.',
   'admin.highAvailability.wizard.step5.header':'Configure Components',
   'admin.highAvailability.wizard.step6.header':'Initialize JournalNodes',
   'admin.highAvailability.wizard.step7.header':'Start Components',

+ 106 - 0
ambari-web/test/controllers/main/admin/highAvailability/nameNode/step4_controller_test.js

@@ -0,0 +1,106 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+describe('App.HighAvailabilityWizardStep4Controller', function() {
+  
+  describe('#checkNnCheckPointStatus', function() {
+    beforeEach(function() {
+      this.controller = App.HighAvailabilityWizardStep4Controller.create();
+      this.clock = sinon.useFakeTimers();
+      sinon.stub(this.controller, 'pullCheckPointStatus');
+    });
+
+    afterEach(function() {
+      this.clock.restore();
+      this.controller.pullCheckPointStatus.restore();
+    });
+
+    var tests = [
+      {
+        responseData: {
+          HostRoles: { desired_state: 'STARTED' }
+        },
+        m: 'NameNode started, Safemode off, no journal node transaction. Polling should be performed and isNameNodeStarted should be true',
+        e: {
+          isPollingCalled: true,
+          isNameNodeStarted: true,
+          isNextEnabled: false
+        }
+      },
+      {
+        responseData: {
+          HostRoles: { desired_state: 'STARTED' },
+          metrics: { dfs: { namenode: {
+            Safemode: 'ON',
+            JournalNodeTransactionInfo: "{\"LastAppliedOrWrittenTxId\":\"4\",\"MostRecentCheckpointTxId\":\"2\"}"
+          }}}
+        },
+        m: 'NameNode started, Safemode on, journal node transaction invalid. Polling should be performed and isNameNodeStarted should be true',
+        e: {
+          isPollingCalled: true,
+          isNameNodeStarted: true,
+          isNextEnabled: false
+        }
+      },
+      {
+        responseData: {
+          HostRoles: { desired_state: 'INSTALLED' },
+          metrics: { dfs: { namenode: {
+            Safemode: 'ON',
+            JournalNodeTransactionInfo: "{\"LastAppliedOrWrittenTxId\":\"15\",\"MostRecentCheckpointTxId\":\"14\"}"
+          }}}
+        },
+        m: 'NameNode not started, Safemode on, journal node transaction present. Polling should not be performed and isNameNodeStarted should be false',
+        e: {
+          isPollingCalled: false,
+          isNameNodeStarted: false,
+          isNextEnabled: true
+        }
+      },
+      {
+        responseData: {
+          HostRoles: { desired_state: 'STARTED' },
+          metrics: { dfs: { namenode: {
+            Safemode: "",
+            JournalNodeTransactionInfo: "{\"LastAppliedOrWrittenTxId\":\"15\",\"MostRecentCheckpointTxId\":\"14\"}"
+          }}}
+        },
+        m: 'NameNode started, Safemode off, journal node transaction present. Polling should not be performed and isNameNodeStarted should be true',
+        e: {
+          isPollingCalled: true,
+          isNameNodeStarted: true,
+          isNextEnabled: false
+        }
+      }
+    ];
+
+    tests.forEach(function(test) {
+      it(test.m, function() {
+        this.controller.set('isNameNodeStarted', !test.e.isNameNodeStarted);
+        this.controller.checkNnCheckPointStatus(test.responseData);
+        this.clock.tick(this.controller.get('POLL_INTERVAL'));
+        expect(this.controller.get('isNameNodeStarted')).to.be.eql(test.e.isNameNodeStarted);
+        expect(this.controller.get('isNextEnabled')).to.be.eql(test.e.isNextEnabled);
+        expect(this.controller.pullCheckPointStatus.called).to.be.eql(test.e.isPollingCalled);
+      });
+    });
+  });
+});
+