Browse Source

AMBARI-5676 Perf: Transition from Install Options to Confirm Hosts took several minutes with browser completely hung with 2000 nodes. (atkach)

atkach 11 years ago
parent
commit
9817682785

+ 50 - 13
ambari-web/app/controllers/wizard.js

@@ -335,34 +335,71 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
     this.saveClusterStatus(clusterStatus);
     App.showAlertPopup(Em.I18n.t('common.errorPopup.header'), request.responseText);
   },
-
-  bootstrapRequestId: null,
-
-  /*
-   Bootstrap selected hosts.
+  /**
+   * show popup, that display status of bootstrap launching
+   * @param callback
+   * @return {Object}
    */
-  launchBootstrap: function (bootStrapData) {
+  showLaunchBootstrapPopup: function (callback) {
+    return App.ModalPopup.show({
+      header: Em.I18n.t('installer.step2.bootStrap.header'),
+      isError: false,
+      serverError: null,
+      bodyClass: Em.View.extend({
+        templateName: require('templates/wizard/bootstrap_call_popup')
+      }),
+      showFooter: false,
+      showCloseButton: false,
+      secondary: null,
+      /**
+       * handle requestId when call is completed,
+       * if it's correct call callback and hide popup
+       * otherwise notify error and enable buttons to close popup
+       * @param requestId
+       * @param serverError
+       */
+      finishLoading: function (requestId, serverError) {
+        if (Em.isNone(requestId)) {
+          this.set('isError', true);
+          this.set('showFooter', true);
+          this.set('showCloseButton', true);
+          this.set('serverError', serverError);
+        } else {
+          callback(requestId);
+          this.hide();
+        }
+      }
+    });
+  },
+  /**
+   * Bootstrap selected hosts.
+   * @param bootStrapData
+   * @param callback
+   * @return {Object}
+   */
+  launchBootstrap: function (bootStrapData, callback) {
+    var popup = this.showLaunchBootstrapPopup(callback);
     App.ajax.send({
       name: 'wizard.launch_bootstrap',
       sender: this,
       data: {
-        bootStrapData: bootStrapData
+        bootStrapData: bootStrapData,
+        popup: popup
       },
       success: 'launchBootstrapSuccessCallback',
       error: 'launchBootstrapErrorCallback'
     });
-
-    return this.get('bootstrapRequestId');
+    return popup;
   },
 
-  launchBootstrapSuccessCallback: function (data) {
+  launchBootstrapSuccessCallback: function (data, opt, params) {
     console.log("TRACE: POST bootstrap succeeded");
-    this.set('bootstrapRequestId', data.requestId);
+    params.popup.finishLoading(data.requestId, null);
   },
 
-  launchBootstrapErrorCallback: function () {
+  launchBootstrapErrorCallback: function (request, ajaxOptions, error, opt, params) {
     console.log("ERROR: POST bootstrap failed");
-    alert('Bootstrap call failed. Please try again.');
+    params.popup.finishLoading(null, error);
   },
 
   /**

+ 21 - 12
ambari-web/app/controllers/wizard/step2_controller.js

@@ -331,24 +331,33 @@ App.WizardStep2Controller = Em.Controller.extend({
       return false;
     }
 
-    var bootStrapData = JSON.stringify({'verbose': true, 'sshKey': this.get('sshKey'), 'hosts': this.get('hostNameArr'), 'user': this.get('sshUser')});
-
     if (App.get('skipBootstrap')) {
       this.saveHosts();
+      App.router.send('next');
       return true;
     }
-
-    var requestId = App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData);
-    if (requestId == '0') {
-      var controller = App.router.get(App.clusterStatus.wizardControllerName);
-      controller.registerErrPopup(Em.I18n.t('common.information'), Em.I18n.t('installer.step2.evaluateStep.hostRegInProgress'));
-    } else if (requestId) {
-      this.set('content.installOptions.bootRequestId', requestId);
-      this.saveHosts();
-    }
+    this.setupBootStrap();
     return true;
   },
 
+  /**
+   * setup bootstrap data and completion callback for bootstrap call
+   */
+  setupBootStrap: function () {
+    var self = this;
+    var bootStrapData = JSON.stringify({'verbose': true, 'sshKey': this.get('sshKey'), 'hosts': this.get('hostNameArr'), 'user': this.get('sshUser')});
+    App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
+      if (requestId == '0') {
+        var controller = App.router.get(App.clusterStatus.wizardControllerName);
+        controller.registerErrPopup(Em.I18n.t('common.information'), Em.I18n.t('installer.step2.evaluateStep.hostRegInProgress'));
+      } else if (requestId) {
+        self.set('content.installOptions.bootRequestId', requestId);
+        self.saveHosts();
+        App.router.send('next');
+      }
+    });
+  },
+
   /**
    * show warning for host names without dots or IP addresses
    * @method warningPopup
@@ -431,6 +440,7 @@ App.WizardStep2Controller = Em.Controller.extend({
       onPrimary: function () {
         this.hide();
         self.saveHosts();
+        App.router.send('next');
       },
       bodyClass: Em.View.extend({
         templateName: require('templates/wizard/step2ManualInstallPopup')
@@ -492,7 +502,6 @@ App.WizardStep2Controller = Em.Controller.extend({
   saveHosts: function () {
     this.set('content.hosts', this.getHostInfo());
     this.setAmbariJavaHome();
-    App.router.send('next');
   }
 
 });

+ 34 - 30
ambari-web/app/controllers/wizard/step3_controller.js

@@ -326,11 +326,12 @@ App.WizardStep3Controller = Em.Controller.extend({
    * @method retryHosts
    */
   retryHosts: function (hosts) {
+    var self = this;
     var bootStrapData = JSON.stringify({
-      'verbose': true,
-      'sshKey': this.get('content.installOptions.sshKey'),
-      'hosts': hosts.mapProperty('name'),
-      'user': this.get('content.installOptions.sshUser')}
+        'verbose': true,
+        'sshKey': this.get('content.installOptions.sshKey'),
+        'hosts': hosts.mapProperty('name'),
+        'user': this.get('content.installOptions.sshUser')}
     );
     this.set('numPolls', 0);
     this.set('registrationStartedAt', null);
@@ -339,9 +340,10 @@ App.WizardStep3Controller = Em.Controller.extend({
       this.startRegistration();
     }
     else {
-      var requestId = App.router.get('installerController').launchBootstrap(bootStrapData);
-      this.set('content.installOptions.bootRequestId', requestId);
-      this.doBootstrap();
+      App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
+        self.set('content.installOptions.bootRequestId', requestId);
+        self.doBootstrap();
+      });
     }
   },
 
@@ -710,7 +712,9 @@ App.WizardStep3Controller = Em.Controller.extend({
       } else if (host) {
         _host.set('cpu', host.Hosts.cpu_count);
         _host.set('memory', ((parseInt(host.Hosts.total_mem))).toFixed(2));
-        _host.set('disk_info', host.Hosts.disk_info.filter(function(host){ return host.mountpoint!="/boot"}));
+        _host.set('disk_info', host.Hosts.disk_info.filter(function (host) {
+          return host.mountpoint != "/boot"
+        }));
         _host.set('os_type', host.Hosts.os_type);
         _host.set('os_arch', host.Hosts.os_arch);
         _host.set('ip', host.Hosts.ip);
@@ -1026,28 +1030,28 @@ App.WizardStep3Controller = Em.Controller.extend({
       //todo: to be removed after check in new API
       var javaProcs = _host.Hosts.last_agent_env.hostHealth ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs : _host.Hosts.last_agent_env.javaProcs;
       if (javaProcs) {
-      javaProcs.forEach(function (process) {
-        warning = warningCategories.processesWarnings[process.pid];
-        if (warning) {
-          warning.hosts.push(_host.Hosts.host_name);
-          warning.onSingleHost = false;
-        } else {
-          warningCategories.processesWarnings[process.pid] = warning = {
-            name: (process.command.substr(0, 35) + '...'),
-            hosts: [_host.Hosts.host_name],
-            category: 'processes',
-            user: process.user,
-            pid: process.pid,
-            command: '<table><tr><td style="word-break: break-all;">' +
-              ((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
-                '<p style="text-align: center">................</p>' +
-                '...' + process.command.substr(-230)) + '</td></tr></table>',
-            onSingleHost: true
-          };
-        }
-        host.warnings.push(warning);
-      }, this);
-    }
+        javaProcs.forEach(function (process) {
+          warning = warningCategories.processesWarnings[process.pid];
+          if (warning) {
+            warning.hosts.push(_host.Hosts.host_name);
+            warning.onSingleHost = false;
+          } else {
+            warningCategories.processesWarnings[process.pid] = warning = {
+              name: (process.command.substr(0, 35) + '...'),
+              hosts: [_host.Hosts.host_name],
+              category: 'processes',
+              user: process.user,
+              pid: process.pid,
+              command: '<table><tr><td style="word-break: break-all;">' +
+                ((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
+                  '<p style="text-align: center">................</p>' +
+                  '...' + process.command.substr(-230)) + '</td></tr></table>',
+              onSingleHost: true
+            };
+          }
+          host.warnings.push(warning);
+        }, this);
+      }
 
       //parse all service warnings for host
 

+ 3 - 0
ambari-web/app/messages.js

@@ -432,6 +432,9 @@ Em.I18n.translations = {
   'installer.step2.sshUser.toolTip':'An account that can execute sudo without entering a password',
   'installer.step2.sshUser.placeholder':'Enter user name',
   'installer.step2.sshUser.required':'User name is required',
+  'installer.step2.bootStrap.error':'Errors were encountered while setting up Ambari Agents on the hosts.',
+  'installer.step2.bootStrap.inProgress':'Please wait while Ambari Agents are being set up on the hosts. This can take several minutes depending on the number of hosts.',
+  'installer.step2.bootStrap.header':'Setting Up Ambari Agents',
 
   'installer.step3.header':'Confirm Hosts',
   'installer.step3.body':'Registering your hosts.<br>' +

+ 34 - 0
ambari-web/app/templates/wizard/bootstrap_call_popup.hbs

@@ -0,0 +1,34 @@
+{{!
+* 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.
+}}
+
+
+{{#if view.parentView.isError}}
+    <div>
+        <div class="alert alert-error">
+          {{t installer.step2.bootStrap.error}}
+        </div>
+      <pre>
+        {{view.parentView.serverError}}
+      </pre>
+    </div>
+{{else}}
+    <div>
+      {{t installer.step2.bootStrap.inProgress}}
+    </div>
+    <div class="spinner"></div>
+{{/if}}

+ 2 - 2
ambari-web/app/utils/ajax/ajax.js

@@ -1618,9 +1618,9 @@ var urls = {
     'type': 'POST',
     'format': function (data) {
       return {
-        async: false,
         contentType: 'application/json',
-        data: data.bootStrapData
+        data: data.bootStrapData,
+        popup: data.popup
       }
     }
   },

+ 6 - 3
ambari-web/test/controllers/wizard_test.js

@@ -88,9 +88,12 @@ describe('App.WizardController', function () {
 
   describe('#launchBootstrapSuccessCallback', function() {
     it('Save bootstrapRequestId', function() {
-      var data = {requestId:123};
-      wizardController.launchBootstrapSuccessCallback(data);
-      expect(wizardController.get('bootstrapRequestId')).to.equal(data.requestId);
+      var data = {requestId: 123};
+      var params = {popup: {finishLoading: function(){}}};
+      sinon.spy(params.popup, "finishLoading");
+      wizardController.launchBootstrapSuccessCallback(data, {}, params);
+      expect(params.popup.finishLoading.calledWith(123)).to.be.true;
+      params.popup.finishLoading.restore();
     });
   });
 

+ 22 - 27
ambari-web/test/installer/step3_test.js

@@ -415,51 +415,46 @@ describe('App.WizardStep3Controller', function () {
     });
   });
 
-  describe('#retryHosts', function() {
-    it('should set numPolls to 0', function() {
-      var s = sinon.stub(App.router, 'get', function() {
-        return {launchBootstrap: Em.K}
+  describe('#retryHosts', function () {
+    var s;
+    var installer = {launchBootstrap: Em.K};
+
+    beforeEach(function () {
+      sinon.spy(installer, "launchBootstrap");
+      s = sinon.stub(App.router, 'get', function () {
+        return installer;
       });
+      sinon.stub(c, 'doBootstrap', Em.K);
+    });
+
+    afterEach(function () {
+      c.doBootstrap.restore();
+      s.restore();
+      installer.launchBootstrap.restore();
+    });
+
+    it('should set numPolls to 0', function () {
       c.set('content', {installOptions: {}});
-      c.set('doBootstrap', Em.K);
       c.set('numPolls', 123);
       c.retryHosts(Em.A([]));
       expect(c.get('numPolls')).to.equal(0);
-      s.restore();
     });
-    it('should set registrationStartedAt to null', function() {
-      var s = sinon.stub(App.router, 'get', function() {
-        return {launchBootstrap: Em.K}
-      });
+    it('should set registrationStartedAt to null', function () {
       c.set('content', {installOptions: {}});
-      c.set('doBootstrap', Em.K);
       c.retryHosts(Em.A([]));
       expect(c.get('registrationStartedAt')).to.be.null;
-      s.restore();
     });
-    it('should startRegistration if installOptions.manualInstall is true', function() {
-      var s = sinon.stub(App.router, 'get', function() {
-        return {launchBootstrap: Em.K}
-      });
+    it('should startRegistration if installOptions.manualInstall is true', function () {
       sinon.spy(c, 'startRegistration');
       c.set('content', {installOptions: {manualInstall: true}});
-      c.set('doBootstrap', Em.K);
       c.retryHosts(Em.A([]));
       expect(c.startRegistration.calledOnce).to.equal(true);
-      s.restore();
       c.startRegistration.restore();
     });
-    it('should doBootstrap if installOptions.manualInstall is false', function() {
-      var s = sinon.stub(App.router, 'get', function() {
-        return {launchBootstrap: Em.K}
-      });
+    it('should launchBootstrap if installOptions.manualInstall is false', function () {
       c.set('content', {installOptions: {manualInstall: false}});
-      c.set('doBootstrap', Em.K);
-      sinon.spy(c, 'doBootstrap');
       c.retryHosts(Em.A([]));
-      expect(c.doBootstrap.calledOnce).to.equal(true);
-      s.restore();
-      c.doBootstrap.restore();
+      expect(installer.launchBootstrap.calledOnce).to.be.true;
     });
   });