Przeglądaj źródła

AMBARI-6026 Convert UI code of Add Host and Add Service Wizards to to lazily load host and host component info. (Max Shepel via atkach)

atkach 11 lat temu
rodzic
commit
587482301f

+ 50 - 17
ambari-web/app/controllers/main/host/add_controller.js

@@ -18,6 +18,7 @@
 
 
 
 
 var App = require('app');
 var App = require('app');
+var lazyLoading = require('utils/lazy_loading');
 
 
 App.AddHostController = App.WizardController.extend({
 App.AddHostController = App.WizardController.extend({
 
 
@@ -128,15 +129,6 @@ App.AddHostController = App.WizardController.extend({
     console.log('selected services ', serviceNames);
     console.log('selected services ', serviceNames);
   },
   },
 
 
-  /**
-   * return slaveComponents bound to hosts
-   * @return {Array}
-   */
-  getSlaveComponentHosts: function () {
-    return this._super().filter(function (component) {
-      return component.isInstalled;
-    });
-  },
 
 
   /**
   /**
    * Load master component hosts data for using in required step controllers
    * Load master component hosts data for using in required step controllers
@@ -144,34 +136,67 @@ App.AddHostController = App.WizardController.extend({
    */
    */
   loadSlaveComponentHosts: function () {
   loadSlaveComponentHosts: function () {
     var slaveComponentHosts = this.getDBProperty('slaveComponentHosts');
     var slaveComponentHosts = this.getDBProperty('slaveComponentHosts');
+    var message = 'AddHostController.loadSlaveComponentHosts: loaded hosts ';
+    var filterFunction = function (component) {
+      return component.isInstalled;
+    };
     if (!slaveComponentHosts) {
     if (!slaveComponentHosts) {
-      slaveComponentHosts = this.getSlaveComponentHosts();
+      this.getSlaveComponentHosts(this, 'content.slaveComponentHosts', message, filterFunction);
+    } else {
+      this.set('content.slaveComponentHosts', []);
+      lazyLoading.run({
+        initSize: 20,
+        chunkSize: 50,
+        delay: 50,
+        destination: this.get('content.slaveComponentHosts'),
+        source: slaveComponentHosts,
+        context: this
+      });
+      console.log(message, slaveComponentHosts);
     }
     }
-    this.set("content.slaveComponentHosts", slaveComponentHosts);
-    console.log("AddHostController.loadSlaveComponentHosts: loaded hosts ", slaveComponentHosts);
   },
   },
 
 
   /**
   /**
    * Generate clients list for selected services and save it to model
    * Generate clients list for selected services and save it to model
    */
    */
   saveClients: function () {
   saveClients: function () {
+
+    App.ajax.send({
+      name: 'host_components.all',
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName')
+      },
+      success: 'saveClientsSuccessCallBack'
+    });
+
+  },
+
+  saveClientsSuccessCallBack: function (response) {
     var clients = [];
     var clients = [];
     var serviceComponents = App.StackServiceComponent.find();
     var serviceComponents = App.StackServiceComponent.find();
-    var hostComponents = App.HostComponent.find();
-
     this.get('content.services').filterProperty('isSelected').forEach(function (_service) {
     this.get('content.services').filterProperty('isSelected').forEach(function (_service) {
       var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient');
       var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient');
       if (client) {
       if (client) {
         clients.push({
         clients.push({
           component_name: client.get('componentName'),
           component_name: client.get('componentName'),
           display_name: client.get('displayName'),
           display_name: client.get('displayName'),
-          isInstalled: hostComponents.filterProperty('componentName', client.get('componentName')).length > 0
+          isInstalled: response.items.filterProperty('HostRoles.component_name', client.get('componentName')).length > 0
         });
         });
       }
       }
     }, this);
     }, this);
 
 
     this.setDBProperty('clientInfo', clients);
     this.setDBProperty('clientInfo', clients);
-    this.set('content.clients', clients);
+    this.set('content.clients', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content.clients'),
+      source: clients,
+      context: this
+    });
+
     console.log("AddHostController.saveClients: saved list ", clients);
     console.log("AddHostController.saveClients: saved list ", clients);
   },
   },
 
 
@@ -289,7 +314,15 @@ App.AddHostController = App.WizardController.extend({
         var service = componentServiceMap[client.component_name];
         var service = componentServiceMap[client.component_name];
         var serviceMatch = selectedServices.findProperty('serviceId', service);
         var serviceMatch = selectedServices.findProperty('serviceId', service);
         if (serviceMatch) {
         if (serviceMatch) {
-          serviceMatch.hosts = serviceMatch.hosts.concat(selectedClientHosts).uniq();
+          lazyLoading.run({
+            initSize: 20,
+            chunkSize: 50,
+            delay: 50,
+            destination: serviceMatch.hosts,
+            source: selectedClientHosts,
+            context: Em.Object.create()
+          });
+          serviceMatch.hosts = serviceMatch.hosts.uniq();
         } else {
         } else {
           var configGroups = this.get('content.configGroups').filterProperty('ConfigGroup.tag', service);
           var configGroups = this.get('content.configGroups').filterProperty('ConfigGroup.tag', service);
           var configGroupsNames = configGroups.mapProperty('ConfigGroup.group_name').sort();
           var configGroupsNames = configGroups.mapProperty('ConfigGroup.group_name').sort();

+ 71 - 43
ambari-web/app/controllers/main/service/add_controller.js

@@ -18,6 +18,7 @@
 
 
 
 
 var App = require('app');
 var App = require('app');
+var lazyLoading = require('utils/lazy_loading');
 App.AddServiceController = App.WizardController.extend({
 App.AddServiceController = App.WizardController.extend({
 
 
   name: 'addServiceController',
   name: 'addServiceController',
@@ -78,21 +79,6 @@ App.AddServiceController = App.WizardController.extend({
    */
    */
   loadConfirmedHosts: function(){
   loadConfirmedHosts: function(){
     var hosts = this.getDBProperty('hosts');
     var hosts = this.getDBProperty('hosts');
-    if(!hosts){
-      var hosts = {};
-
-      App.Host.find().forEach(function(item){
-        hosts[item.get('id')] = {
-          name: item.get('id'),
-          cpu: item.get('cpu'),
-          memory: item.get('memory'),
-          disk_info: item.get('diskInfo'),
-          bootStatus: "REGISTERED",
-          isInstalled: true
-        };
-      });
-      this.setDBProperty('hosts', hosts);
-    }
 
 
     this.set('content.hosts', hosts);
     this.set('content.hosts', hosts);
     console.log('AddServiceController.loadConfirmedHosts: loaded hosts', hosts);
     console.log('AddServiceController.loadConfirmedHosts: loaded hosts', hosts);
@@ -161,33 +147,44 @@ App.AddServiceController = App.WizardController.extend({
    * @param stepController App.WizardStep5Controller
    * @param stepController App.WizardStep5Controller
    */
    */
   saveMasterComponentHosts: function (stepController) {
   saveMasterComponentHosts: function (stepController) {
-    var obj = stepController.get('selectedServicesMasters');
-    var masterComponentHosts = [];
-    var installedComponents = App.HostComponent.find();
 
 
+    App.ajax.send({
+      name: 'host_components.all',
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName'),
+        stepController: stepController
+      },
+      success: 'saveMasterComponentHostsSuccessCallback'
+    });
+
+  },
+
+  saveMasterComponentHostsSuccessCallback: function (response, request, data) {
+    var obj = data.stepController.get('selectedServicesMasters');
+    var masterComponentHosts = [];
     obj.forEach(function (_component) {
     obj.forEach(function (_component) {
-        masterComponentHosts.push({
-          display_name: _component.display_name,
-          component: _component.component_name,
-          hostName: _component.selectedHost,
-          serviceId: _component.serviceId,
-          isInstalled: installedComponents.someProperty('componentName', _component.component_name)
-        });
+      masterComponentHosts.push({
+        display_name: _component.display_name,
+        component: _component.component_name,
+        hostName: _component.selectedHost,
+        serviceId: _component.serviceId,
+        isInstalled: response.items.someProperty('HostRoles.component_name', _component.component_name)
+      });
     });
     });
 
 
     console.log("AddServiceController.saveMasterComponentHosts: saved hosts ", masterComponentHosts);
     console.log("AddServiceController.saveMasterComponentHosts: saved hosts ", masterComponentHosts);
     this.setDBProperty('masterComponentHosts', masterComponentHosts);
     this.setDBProperty('masterComponentHosts', masterComponentHosts);
-    this.set('content.masterComponentHosts', masterComponentHosts);
-
-    this.set('content.skipMasterStep', this.get('content.masterComponentHosts').everyProperty('isInstalled', true));
-    this.get('isStepDisabled').findProperty('step', 2).set('value', this.get('content.skipMasterStep'));
-  },
+    this.set('content.masterComponentHosts', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content.masterComponentHosts'),
+      source: masterComponentHosts,
+      context: this
+    });
 
 
-  /**
-   * Load master component hosts data for using in required step controllers
-   */
-  loadMasterComponentHosts: function () {
-    this._super();
     this.set('content.skipMasterStep', this.get('content.masterComponentHosts').everyProperty('isInstalled', true));
     this.set('content.skipMasterStep', this.get('content.masterComponentHosts').everyProperty('isInstalled', true));
     this.get('isStepDisabled').findProperty('step', 2).set('value', this.get('content.skipMasterStep'));
     this.get('isStepDisabled').findProperty('step', 2).set('value', this.get('content.skipMasterStep'));
   },
   },
@@ -238,11 +235,22 @@ App.AddServiceController = App.WizardController.extend({
    */
    */
   loadSlaveComponentHosts: function () {
   loadSlaveComponentHosts: function () {
     var slaveComponentHosts = this.getDBProperty('slaveComponentHosts');
     var slaveComponentHosts = this.getDBProperty('slaveComponentHosts');
+    var message = 'AddServiceController.loadSlaveComponentHosts: loaded hosts ';
+    this.set('content.slaveComponentHosts', []);
     if(!slaveComponentHosts){
     if(!slaveComponentHosts){
-      slaveComponentHosts = this.getSlaveComponentHosts();
+      this.getSlaveComponentHosts(this, 'content.slaveComponentHosts', message);
+    } else {
+      this.set('content.slaveComponentHosts', []);
+      lazyLoading.run({
+        initSize: 20,
+        chunkSize: 50,
+        delay: 50,
+        destination: this.get('content.slaveComponentHosts'),
+        source: slaveComponentHosts,
+        context: this
+      });
+      console.log(message, slaveComponentHosts);
     }
     }
-    this.set("content.slaveComponentHosts", slaveComponentHosts);
-    console.log("AddServiceController.loadSlaveComponentHosts: loaded hosts ", slaveComponentHosts);
   },
   },
 
 
   /**
   /**
@@ -250,23 +258,43 @@ App.AddServiceController = App.WizardController.extend({
    * @param stepController step4WizardController
    * @param stepController step4WizardController
    */
    */
   saveClients: function(stepController){
   saveClients: function(stepController){
+
+    App.ajax.send({
+      name: 'host_components.all',
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName'),
+        stepController: stepController
+      },
+      success: 'saveClientsSuccessCallback'
+    });
+
+  },
+
+  saveClientsSuccessCallback: function (response, request, data) {
     var clients = [];
     var clients = [];
     var serviceComponents = App.StackServiceComponent.find();
     var serviceComponents = App.StackServiceComponent.find();
-    var hostComponents = App.HostComponent.find();
-
-    stepController.get('content').filterProperty('isSelected',true).forEach(function (_service) {
+    data.stepController.get('content').filterProperty('isSelected',true).forEach(function (_service) {
       var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient', true);
       var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient', true);
       if (client) {
       if (client) {
         clients.pushObject({
         clients.pushObject({
           component_name: client.get('componentName'),
           component_name: client.get('componentName'),
           display_name: client.get('displayName'),
           display_name: client.get('displayName'),
-          isInstalled: hostComponents.filterProperty('componentName', client.get('componentName')).length > 0
+          isInstalled: response.items.filterProperty('HostRoles.component_name', client.get('componentName')).length > 0
         });
         });
       }
       }
     }, this);
     }, this);
 
 
     this.setDBProperty('clientInfo', clients);
     this.setDBProperty('clientInfo', clients);
-    this.set('content.clients', clients);
+    this.set('content.clients', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content.clients'),
+      source: clients,
+      context: this
+    });
     console.log("AddServiceController.saveClients: saved list ", clients);
     console.log("AddServiceController.saveClients: saved list ", clients);
   },
   },
 
 

+ 84 - 15
ambari-web/app/controllers/wizard.js

@@ -18,6 +18,7 @@
 
 
 
 
 var App = require('app');
 var App = require('app');
+var lazyLoading = require('utils/lazy_loading');
 require('models/host');
 require('models/host');
 
 
 App.WizardController = Em.Controller.extend(App.LocalStorage, {
 App.WizardController = Em.Controller.extend(App.LocalStorage, {
@@ -58,8 +59,6 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
     return App.StackServiceComponent.find().filterProperty('isSlave',true);
     return App.StackServiceComponent.find().filterProperty('isSlave',true);
   }.property('App.router.clusterController.isLoaded'),
   }.property('App.router.clusterController.isLoaded'),
 
 
-  allHosts: App.Host.find(),
-
   setStepsEnable: function () {
   setStepsEnable: function () {
     for (var i = 1; i <= this.totalSteps; i++) {
     for (var i = 1; i <= this.totalSteps; i++) {
       var step = this.get('isStepDisabled').findProperty('step', i);
       var step = this.get('isStepDisabled').findProperty('step', i);
@@ -798,18 +797,40 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
         });
         });
         // if modified configs detected push all service's configs for update
         // if modified configs detected push all service's configs for update
         if (configs.length)
         if (configs.length)
-          updateServiceConfigProperties = updateServiceConfigProperties.concat(serviceConfigProperties.filterProperty('serviceName',_content.get('serviceName')));
+         lazyLoading.run({
+            initSize: 20,
+            chunkSize: 50,
+            delay: 50,
+            destination: updateServiceConfigProperties,
+            source: serviceConfigProperties.filterProperty('serviceName',_content.get('serviceName')),
+            context: this
+          });
         // watch for properties that are not modified but have to be updated
         // watch for properties that are not modified but have to be updated
         if (_content.get('configs').someProperty('forceUpdate')) {
         if (_content.get('configs').someProperty('forceUpdate')) {
           // check for already added modified properties
           // check for already added modified properties
           if (!updateServiceConfigProperties.findProperty('serviceName', _content.get('serviceName'))) {
           if (!updateServiceConfigProperties.findProperty('serviceName', _content.get('serviceName'))) {
-            updateServiceConfigProperties = updateServiceConfigProperties.concat(serviceConfigProperties.filterProperty('serviceName',_content.get('serviceName')));
+            lazyLoading.run({
+              initSize: 20,
+              chunkSize: 50,
+              delay: 50,
+              destination: updateServiceConfigProperties,
+              source: serviceConfigProperties.filterProperty('serviceName',_content.get('serviceName')),
+              context: this
+            });
           }
           }
         }
         }
       }
       }
     }, this);
     }, this);
     this.setDBProperty('serviceConfigProperties', serviceConfigProperties);
     this.setDBProperty('serviceConfigProperties', serviceConfigProperties);
-    this.set('content.serviceConfigProperties', serviceConfigProperties);
+    this.set('content.serviceConfigProperties', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content.serviceConfigProperties'),
+      source: serviceConfigProperties,
+      context: this
+    });
     this.setDBProperty('configsToUpdate', updateServiceConfigProperties);
     this.setDBProperty('configsToUpdate', updateServiceConfigProperties);
   },
   },
   /**
   /**
@@ -847,14 +868,21 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
     }, this);
     }, this);
     this.setDBProperty('serviceConfigGroups', serviceConfigGroups);
     this.setDBProperty('serviceConfigGroups', serviceConfigGroups);
     this.set('content.configGroups', serviceConfigGroups);
     this.set('content.configGroups', serviceConfigGroups);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content.configGroups'),
+      source: serviceConfigGroups,
+      context: this
+    });
   },
   },
   /**
   /**
    * return slaveComponents bound to hosts
    * return slaveComponents bound to hosts
    * @return {Array}
    * @return {Array}
    */
    */
-  getSlaveComponentHosts: function () {
+  getSlaveComponentHosts: function (context, property, message, filterFunction) {
     var components = this.get('slaveComponents');
     var components = this.get('slaveComponents');
-    var result = [];
     var installedServices = App.Service.find().mapProperty('serviceName');
     var installedServices = App.Service.find().mapProperty('serviceName');
     var selectedServices = this.get('content.services').filterProperty('isSelected', true).mapProperty('serviceName');
     var selectedServices = this.get('content.services').filterProperty('isSelected', true).mapProperty('serviceName');
     var installedComponentsMap = {};
     var installedComponentsMap = {};
@@ -869,13 +897,33 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
     }, this);
     }, this);
     installedComponentsMap['HDFS_CLIENT'] = [];
     installedComponentsMap['HDFS_CLIENT'] = [];
 
 
-    App.HostComponent.find().forEach(function (hostComponent) {
-      if (installedComponentsMap[hostComponent.get('componentName')]) {
-        installedComponentsMap[hostComponent.get('componentName')].push(hostComponent.get('host.id'));
+    App.ajax.send({
+      name: 'host_components.all',
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName'),
+        installedComponentsMap: installedComponentsMap,
+        uninstalledComponents: uninstalledComponents,
+        context: context,
+        property: property,
+        message: message,
+        filterFunction: filterFunction
+      },
+      success: 'getSlaveComponentHostsSuccessCallback'
+    });
+
+  },
+
+  getSlaveComponentHostsSuccessCallback: function (response, request, data) {
+    var result = [];
+
+    response.items.mapProperty('HostRoles').forEach(function (hostComponent) {
+      if (data.installedComponentsMap[hostComponent.component_name]) {
+        data.installedComponentsMap[hostComponent.component_name].push(hostComponent.host_name);
       }
       }
     }, this);
     }, this);
 
 
-    for (var componentName in installedComponentsMap) {
+    for (var componentName in data.installedComponentsMap) {
       var name = (componentName === 'HDFS_CLIENT') ? 'CLIENT' : componentName;
       var name = (componentName === 'HDFS_CLIENT') ? 'CLIENT' : componentName;
       var component = {
       var component = {
         componentName: name,
         componentName: name,
@@ -883,7 +931,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
         hosts: [],
         hosts: [],
         isInstalled: true
         isInstalled: true
       };
       };
-      installedComponentsMap[componentName].forEach(function (hostName) {
+      data.installedComponentsMap[componentName].forEach(function (hostName) {
         component.hosts.push({
         component.hosts.push({
           group: "Default",
           group: "Default",
           hostName: hostName,
           hostName: hostName,
@@ -893,7 +941,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
       result.push(component);
       result.push(component);
     }
     }
 
 
-    uninstalledComponents.forEach(function (component) {
+    data.uninstalledComponents.forEach(function (component) {
       var hosts = jQuery.extend(true, [], result.findProperty('componentName', 'DATANODE').hosts);
       var hosts = jQuery.extend(true, [], result.findProperty('componentName', 'DATANODE').hosts);
       hosts.setEach('isInstalled', false);
       hosts.setEach('isInstalled', false);
       result.push({
       result.push({
@@ -904,7 +952,20 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
       })
       })
     });
     });
 
 
-    return result;
+    if (data.filterFunction) {
+      result = result.filter(data.filterFunction);
+    }
+
+    data.context.set(data.property, []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: data.context.get(data.property),
+      source: result,
+      context: this
+    });
+    console.log(data.message, result);
   },
   },
   /**
   /**
    * Load master component hosts data for using in required step controllers
    * Load master component hosts data for using in required step controllers
@@ -931,7 +992,15 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
    */
    */
   loadClients: function () {
   loadClients: function () {
     var clients = this.getDBProperty('clientInfo');
     var clients = this.getDBProperty('clientInfo');
-    this.set('content.clients', clients);
+    this.set('content.clients', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content.clients'),
+      source: clients,
+      context: this
+    });
     console.log(this.get('content.controllerName') + ".loadClients: loaded list ", clients);
     console.log(this.get('content.controllerName') + ".loadClients: loaded list ", clients);
   }
   }
 });
 });

+ 43 - 14
ambari-web/app/controllers/wizard/step10_controller.js

@@ -17,6 +17,7 @@
  */
  */
 
 
 var App = require('app');
 var App = require('app');
+var lazyLoading = require('utils/lazy_loading');
 
 
 App.WizardStep10Controller = Em.Controller.extend({
 App.WizardStep10Controller = Em.Controller.extend({
 
 
@@ -56,16 +57,7 @@ App.WizardStep10Controller = Em.Controller.extend({
   loadStep: function () {
   loadStep: function () {
     console.log("TRACE: Loading step10: Summary Page");
     console.log("TRACE: Loading step10: Summary Page");
     this.clearStep();
     this.clearStep();
-    this.loadInstalledHosts(this.loadRegisteredHosts());
-    var installFlag = true;
-    var startFlag = true;
-    if (this.get('content.controllerName') == 'installerController') {
-      installFlag = this.loadMasterComponents();
-      startFlag = this.loadStartedServices();
-    }
-    if (installFlag && startFlag) {
-      this.loadInstallTime();
-    }
+    this.loadRegisteredHosts();
   },
   },
 
 
   /**
   /**
@@ -74,14 +66,41 @@ App.WizardStep10Controller = Em.Controller.extend({
    * @method loadRegisteredHosts
    * @method loadRegisteredHosts
    */
    */
   loadRegisteredHosts: function () {
   loadRegisteredHosts: function () {
+    var clusterName = (this.get('content.controllerName') === 'installerController') ? this.get('content.cluster.name') : App.get('clusterName')
+    App.ajax.send({
+      name: 'hosts.all',
+      sender: this,
+      data: {
+        clusterName: clusterName
+      },
+      success: 'loadRegisteredHostsSuccessCallback'
+    });
+  },
+
+  loadRegisteredHostsSuccessCallback: function (response) {
     var masterHosts = this.get('content.masterComponentHosts').mapProperty('hostName').uniq();
     var masterHosts = this.get('content.masterComponentHosts').mapProperty('hostName').uniq();
-    var slaveHosts = this.get('content.slaveComponentHosts');
+    var slaveHosts = [];
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: slaveHosts,
+      source: this.get('content.slaveComponentHosts'),
+      context: Em.Object.create()
+    });
     var hostObj = [];
     var hostObj = [];
     slaveHosts.forEach(function (_hosts) {
     slaveHosts.forEach(function (_hosts) {
-      hostObj = hostObj.concat(_hosts.hosts);
+      lazyLoading.run({
+        initSize: 20,
+        chunkSize: 50,
+        delay: 50,
+        destination: hostObj,
+        source: _hosts.hosts,
+        context: Em.Object.create()
+      });
     }, this);
     }, this);
     slaveHosts = hostObj.mapProperty('hostName').uniq();
     slaveHosts = hostObj.mapProperty('hostName').uniq();
-    var registeredHosts = App.Host.find().mapProperty('hostName').concat(masterHosts.concat(slaveHosts)).uniq();
+    var registeredHosts = response.items.mapProperty('Hosts.host_name').concat(masterHosts.concat(slaveHosts)).uniq();
     var registerHostsStatement = Em.I18n.t('installer.step10.hostsSummary').format(registeredHosts.length);
     var registerHostsStatement = Em.I18n.t('installer.step10.hostsSummary').format(registeredHosts.length);
     var registerHostsObj = Em.Object.create({
     var registerHostsObj = Em.Object.create({
       id: 1,
       id: 1,
@@ -91,7 +110,17 @@ App.WizardStep10Controller = Em.Controller.extend({
     });
     });
     this.get('clusterInfo').pushObject(registerHostsObj);
     this.get('clusterInfo').pushObject(registerHostsObj);
 
 
-    return registerHostsObj;
+    this.loadInstalledHosts();
+    var installFlag = true;
+    var startFlag = true;
+    if (this.get('content.controllerName') == 'installerController') {
+      installFlag = this.loadMasterComponents();
+      startFlag = this.loadStartedServices();
+    }
+    if (installFlag && startFlag) {
+      this.loadInstallTime();
+    }
+    this.set('isLoaded', true);
   },
   },
 
 
   /**
   /**

+ 39 - 4
ambari-web/app/controllers/wizard/step2_controller.js

@@ -148,10 +148,30 @@ App.WizardStep2Controller = Em.Controller.extend({
    * @method updateHostNameArr
    * @method updateHostNameArr
    */
    */
   updateHostNameArr: function () {
   updateHostNameArr: function () {
-    this.set('hostNameArr', this.get('hostNames').trim().split(new RegExp("\\s+", "g")));
+    this.set('hostNameArr', []);
+    lazyloading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('hostNameArr'),
+      source: this.get('hostNames').trim().split(new RegExp("\\s+", "g")),
+      context: this
+    });
     this.parseHostNamesAsPatternExpression();
     this.parseHostNamesAsPatternExpression();
     this.get('inputtedAgainHostNames').clear();
     this.get('inputtedAgainHostNames').clear();
-    var installedHostNames = App.Host.find().mapProperty('hostName'),
+    var requestName = (this.get('content.controllerName') == 'installerController') ? 'hosts.all.install' : 'hosts.all';
+    App.ajax.send({
+      name: requestName,
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName')
+      },
+      success: 'updateHostNameArrSuccessCallback'
+    });
+  },
+
+  updateHostNameArrSuccessCallback: function (response) {
+    var installedHostNames = response.items.mapProperty('Hosts.host_name'),
       tempArr = [],
       tempArr = [],
       hostNameArr = this.get('hostNameArr');
       hostNameArr = this.get('hostNameArr');
     for (var i = 0; i < hostNameArr.length; i++) {
     for (var i = 0; i < hostNameArr.length; i++) {
@@ -162,7 +182,14 @@ App.WizardStep2Controller = Em.Controller.extend({
         this.get('inputtedAgainHostNames').push(hostNameArr[i]);
         this.get('inputtedAgainHostNames').push(hostNameArr[i]);
       }
       }
     }
     }
-    this.set('hostNameArr', tempArr);
+    lazyloading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('hostNameArr'),
+      source: tempArr,
+      context: this
+    });
   },
   },
 
 
   /**
   /**
@@ -311,7 +338,15 @@ App.WizardStep2Controller = Em.Controller.extend({
         hostNames.push(a);
         hostNames.push(a);
       }
       }
     });
     });
-    this.set('hostNameArr', hostNames);
+    this.set('hostNameArr', []);
+    lazyloading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('hostNameArr'),
+      source: hostNames,
+      context: this
+    });
   },
   },
 
 
   /**
   /**

+ 89 - 13
ambari-web/app/controllers/wizard/step3_controller.js

@@ -95,9 +95,7 @@ App.WizardStep3Controller = Em.Controller.extend({
    * List of installed hostnames
    * List of installed hostnames
    * @type {string[]}
    * @type {string[]}
    */
    */
-  hostsInCluster: function () {
-    return App.Host.find().getEach('hostName');
-  }.property().volatile(),
+  hostsInCluster: [],
 
 
   /**
   /**
    * All hosts warnings
    * All hosts warnings
@@ -151,6 +149,14 @@ App.WizardStep3Controller = Em.Controller.extend({
    */
    */
   checksUpdateStatus: null,
   checksUpdateStatus: null,
 
 
+  /**
+   * Message about other registered hosts (not included in current registration)
+   * @type {string}
+   */
+  registeredHostsMessage: '',
+
+  /**
+
   /**
   /**
    *
    *
    * @method navigateStep
    * @method navigateStep
@@ -162,7 +168,15 @@ App.WizardStep3Controller = Em.Controller.extend({
           this.startBootstrap();
           this.startBootstrap();
         }
         }
       } else {
       } else {
-        this.set('bootHosts', this.get('hosts'));
+        this.set('bootHosts', []);
+        lazyloading.run({
+          initSize: 20,
+          chunkSize: 50,
+          delay: 200,
+          destination: this.get('bootHosts'),
+          source: this.get('hosts'),
+          context: Em.Object.create()
+        });
         if (App.get('testMode')) {
         if (App.get('testMode')) {
           this.startHostcheck();
           this.startHostcheck();
           this.get('bootHosts').setEach('cpu', '2');
           this.get('bootHosts').setEach('cpu', '2');
@@ -223,8 +237,15 @@ App.WizardStep3Controller = Em.Controller.extend({
         }));
         }));
       }
       }
     }
     }
-    this.set('hosts', hosts);
-    this.set('isLoaded', true);
+    this.set('hosts', []);
+    lazyloading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('hosts'),
+      source: hosts,
+      context: this
+    });
   },
   },
 
 
   /**
   /**
@@ -638,20 +659,59 @@ App.WizardStep3Controller = Em.Controller.extend({
    * @method getAllRegisteredHostsCallback
    * @method getAllRegisteredHostsCallback
    */
    */
   getAllRegisteredHostsCallback: function (hosts) {
   getAllRegisteredHostsCallback: function (hosts) {
-    var registeredHosts = [];
-    var hostsInCluster = this.get('hostsInCluster');
-    var addedHosts = this.get('bootHosts').getEach('name');
-    hosts.items.forEach(function (host) {
+    App.ajax.send({
+      name: 'hosts.all.install',
+      sender: this,
+      data: {
+        hosts: hosts
+      },
+      success: 'hostsInClusterSuccessCallback',
+      error: ''
+    });
+  },
+
+  hostsInClusterSuccessCallback: function (response, request, data) {
+    this.set('hostsInCluster', []);
+    lazyloading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('hostsInCluster'),
+      source: response.items.getEach('Hosts.host_name'),
+      context: Em.Object.create()
+    });
+    var registeredHosts = [],
+      hostsInCluster = [],
+      addedHosts = [];
+    lazyloading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: addedHosts,
+      source: this.get('bootHosts').getEach('name'),
+      context: Em.Object.create()
+    });
+    data.hosts.items.forEach(function (host) {
       if (!hostsInCluster.contains(host.Hosts.host_name) && !addedHosts.contains(host.Hosts.host_name)) {
       if (!hostsInCluster.contains(host.Hosts.host_name) && !addedHosts.contains(host.Hosts.host_name)) {
         registeredHosts.push(host.Hosts.host_name);
         registeredHosts.push(host.Hosts.host_name);
       }
       }
     });
     });
     if (registeredHosts.length) {
     if (registeredHosts.length) {
       this.set('hasMoreRegisteredHosts', true);
       this.set('hasMoreRegisteredHosts', true);
-      this.set('registeredHosts', registeredHosts);
+      this.set('registeredHosts', []);
+      lazyloading.run({
+        initSize: 20,
+        chunkSize: 50,
+        delay: 50,
+        destination: this.get('registeredHosts'),
+        source: registeredHosts,
+        context: this
+      });
+      this.set('registeredHostsMessage', Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('registeredHosts').length))
     } else {
     } else {
       this.set('hasMoreRegisteredHosts', false);
       this.set('hasMoreRegisteredHosts', false);
       this.set('registeredHosts', '');
       this.set('registeredHosts', '');
+      this.set('isLoaded', true);
     }
     }
   },
   },
 
 
@@ -1035,13 +1095,29 @@ App.WizardStep3Controller = Em.Controller.extend({
       var self = this;
       var self = this;
       return App.showConfirmationPopup(
       return App.showConfirmationPopup(
         function () {
         function () {
-          self.set('content.hosts', self.get('bootHosts'));
+          self.set('content.hosts', []);
+          lazyloading.run({
+            initSize: 20,
+            chunkSize: 50,
+            delay: 50,
+            destination: self.get('content.hosts'),
+            source: self.get('bootHosts'),
+            context: Em.Object.create()
+          });
           App.router.send('next');
           App.router.send('next');
         },
         },
         Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
         Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
     }
     }
     else {
     else {
-      this.set('content.hosts', this.get('bootHosts'));
+      this.set('content.hosts', []);
+      lazyloading.run({
+        initSize: 20,
+        chunkSize: 50,
+        delay: 50,
+        destination: this.get('content.hosts'),
+        source: this.get('bootHosts'),
+        context: Em.Object.create()
+      });
       App.router.send('next');
       App.router.send('next');
     }
     }
     return null;
     return null;

+ 80 - 14
ambari-web/app/controllers/wizard/step5_controller.js

@@ -18,6 +18,7 @@
 
 
 var App = require('app');
 var App = require('app');
 var numberUtils = require('utils/number_utils');
 var numberUtils = require('utils/number_utils');
+var lazyLoading = require('utils/lazy_loading');
 
 
 App.WizardStep5Controller = Em.Controller.extend({
 App.WizardStep5Controller = Em.Controller.extend({
 
 
@@ -65,24 +66,38 @@ App.WizardStep5Controller = Em.Controller.extend({
    */
    */
   multipleComponents: ['ZOOKEEPER_SERVER', 'HBASE_MASTER'],
   multipleComponents: ['ZOOKEEPER_SERVER', 'HBASE_MASTER'],
 
 
+  submitDisabled: false,
+
   /**
   /**
    * Define state for submit button. Return true only for Reassign Master Wizard and if more than one master component was reassigned.
    * Define state for submit button. Return true only for Reassign Master Wizard and if more than one master component was reassigned.
    * @type {bool}
    * @type {bool}
    */
    */
   isSubmitDisabled: function () {
   isSubmitDisabled: function () {
     if (!this.get('isReassignWizard')) {
     if (!this.get('isReassignWizard')) {
-      return false;
+      this.set('submitDisabled', false);
+    } else {
+      App.ajax.send({
+        name: 'host_components.all',
+        sender: this,
+        data: {
+          clusterName: App.get('clusterName')
+        },
+        success: 'isSubmitDisabledSuccessCallBack'
+      });
     }
     }
+  }.observes('servicesMasters.@each.selectedHost'),
+
+  isSubmitDisabledSuccessCallBack: function (response) {
     var reassigned = 0;
     var reassigned = 0;
-    var arr1 = App.HostComponent.find().filterProperty('componentName', this.get('content.reassign.component_name')).mapProperty('host.hostName');
+    var arr1 = response.items.mapProperty('HostRoles').filterProperty('component_name', this.get('content.reassign.component_name')).mapProperty('host_name');
     var arr2 = this.get('servicesMasters').mapProperty('selectedHost');
     var arr2 = this.get('servicesMasters').mapProperty('selectedHost');
     arr1.forEach(function (host) {
     arr1.forEach(function (host) {
       if (!arr2.contains(host)) {
       if (!arr2.contains(host)) {
         reassigned++;
         reassigned++;
       }
       }
     }, this);
     }, this);
-    return reassigned !== 1;
-  }.property('servicesMasters.@each.selectedHost'),
+    this.set('submitDisabled', reassigned !== 1);
+  },
 
 
   /**
   /**
    * List of hosts
    * List of hosts
@@ -133,32 +148,73 @@ App.WizardStep5Controller = Em.Controller.extend({
    * </code>
    * </code>
    * @type {Ember.Enumerable}
    * @type {Ember.Enumerable}
    */
    */
-  masterHostMapping: function () {
+  masterHostMapping: [],
+
+  isLoaded: false,
+
+  /**
+   * Check if HIVE_SERVER component exist (also checks if this is not reassign)
+   * @type {bool}
+   */
+  hasHiveServer: function () {
+    return this.get('selectedServicesMasters').someProperty('component_name', 'HIVE_SERVER') && !this.get('isReassignWizard');
+  }.property('selectedServicesMasters'),
+
+  masterHostMappingObserver: function () {
+    var requestName = this.get('content.controllerName') == 'installerController' ? 'hosts.confirmed.install' : 'hosts.confirmed'
+    App.ajax.send({
+      name: requestName,
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName')
+      },
+      success: 'masterHostMappingSuccessCallback'
+    });
+  }.observes('selectedServicesMasters', 'selectedServicesMasters.@each.selectedHost'),
+
+  masterHostMappingSuccessCallback: function (response) {
     var mapping = [], mappingObject, mappedHosts, hostObj;
     var mapping = [], mappingObject, mappedHosts, hostObj;
     //get the unique assigned hosts and find the master services assigned to them
     //get the unique assigned hosts and find the master services assigned to them
-    mappedHosts = this.get("selectedServicesMasters").mapProperty("selectedHost").uniq();
+    mappedHosts = this.get("selectedServicesMasters").mapProperty("selectedHost").uniq().without(undefined);
     mappedHosts.forEach(function (item) {
     mappedHosts.forEach(function (item) {
-      hostObj = this.get("hosts").findProperty("host_name", item);
+      var host = response.items.mapProperty('Hosts').findProperty('host_name', item);
+      hostObj = {
+        name: host.host_name,
+        memory: host.total_mem,
+        cpu: host.cpu_count
+      };
 
 
       mappingObject = Em.Object.create({
       mappingObject = Em.Object.create({
         host_name: item,
         host_name: item,
-        hostInfo: hostObj.host_info,
+        hostInfo: Em.I18n.t('installer.step5.hostInfo').fmt(hostObj.name, numberUtils.bytesToSize(hostObj.memory, 1, 'parseFloat', 1024), hostObj.cpu),
         masterServices: this.get("selectedServicesMasters").filterProperty("selectedHost", item)
         masterServices: this.get("selectedServicesMasters").filterProperty("selectedHost", item)
       });
       });
 
 
       mapping.pushObject(mappingObject);
       mapping.pushObject(mappingObject);
     }, this);
     }, this);
 
 
-    return mapping.sortProperty('host_name');
-  }.property("selectedServicesMasters.@each.selectedHost"),
+    this.set('masterHostMapping', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('masterHostMapping'),
+      source: mapping.sortProperty('host_name'),
+      context: Em.Object.create()
+    });
+  },
 
 
   /**
   /**
    * Count of hosts without masters
    * Count of hosts without masters
    * @type {number}
    * @type {number}
    */
    */
   remainingHosts: function () {
   remainingHosts: function () {
-    return (this.get("hosts.length") - this.get("masterHostMapping.length"));
-  }.property("selectedServicesMasters.@each.selectedHost"),
+    if (this.get('content.controllerName') === 'installerController') {
+     return 0;
+    } else {
+      return (this.get("hosts.length") - this.get("masterHostMapping.length"));
+    };
+  }.property('masterHostMapping.length', 'selectedServicesMasters.@each.selectedHost'),
 
 
   /**
   /**
    * Clear controller data (hosts, masters etc)
    * Clear controller data (hosts, masters etc)
@@ -235,8 +291,17 @@ App.WizardStep5Controller = Em.Controller.extend({
         }));
         }));
       }
       }
     }
     }
-    this.set("hosts", result);
+    this.set("hosts", []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('hosts'),
+      source: result,
+      context: Em.Object.create()
+    });
     this.sortHosts(this.get('hosts'));
     this.sortHosts(this.get('hosts'));
+    this.set('isLoaded', true);
   },
   },
 
 
   /**
   /**
@@ -626,7 +691,8 @@ App.WizardStep5Controller = Em.Controller.extend({
    * @metohd submit
    * @metohd submit
    */
    */
   submit: function () {
   submit: function () {
-    if (!this.get('isSubmitDisabled')) {
+    this.isSubmitDisabled();
+    if (!this.get('submitDisabled')) {
       App.router.send('next');
       App.router.send('next');
     }
     }
   }
   }

+ 25 - 6
ambari-web/app/controllers/wizard/step6_controller.js

@@ -342,17 +342,13 @@ App.WizardStep6Controller = Em.Controller.extend({
     return hostNames;
     return hostNames;
   },
   },
 
 
-  /**
-   * Load all data needed for this module. Then it automatically renders in template
-   * @method render
-   */
-  render: function () {
+  renderHostNames: function (array) {
     var hostsObj = [],
     var hostsObj = [],
       masterHosts = [],
       masterHosts = [],
       headers = this.get('headers'),
       headers = this.get('headers'),
       masterHostNames = this.get('content.masterComponentHosts').mapProperty('hostName').uniq();
       masterHostNames = this.get('content.masterComponentHosts').mapProperty('hostName').uniq();
 
 
-    this.getHostNames().forEach(function (_hostName) {
+    array.forEach(function (_hostName) {
       var hasMaster = masterHostNames.contains(_hostName);
       var hasMaster = masterHostNames.contains(_hostName);
 
 
       var obj = Em.Object.create({
       var obj = Em.Object.create({
@@ -392,6 +388,29 @@ App.WizardStep6Controller = Em.Controller.extend({
     this.set('isLoaded', true);
     this.set('isLoaded', true);
   },
   },
 
 
+  /**
+   * Load all data needed for this module. Then it automatically renders in template
+   * @method render
+   */
+  render: function () {
+    if (this.get('isInstallerWizard') || this.get('isAddHostWizard')) {
+      this.renderHostNames(this.getHostNames());
+    } else {
+      App.ajax.send({
+        name: 'hosts.all',
+        sender: this,
+        data: {
+          clusterName: App.get('clusterName')
+        },
+        success: 'getHostNamesSuccessCallback'
+      });
+    }
+  },
+
+  getHostNamesSuccessCallback: function (response) {
+    this.renderHostNames(response.items.mapProperty('Hosts.host_name'));
+  },
+
   /**
   /**
    * Set checked values for slaves checkboxes
    * Set checked values for slaves checkboxes
    * @param {Array} hostsObj
    * @param {Array} hostsObj

+ 39 - 5
ambari-web/app/controllers/wizard/step7_controller.js

@@ -18,6 +18,8 @@
 
 
 var App = require('app');
 var App = require('app');
 var numberUtils = require('utils/number_utils');
 var numberUtils = require('utils/number_utils');
+var lazyLoading = require('utils/lazy_loading');
+
 /**
 /**
  * By Step 7, we have the following information stored in App.db and set on this
  * By Step 7, we have the following information stored in App.db and set on this
  * controller by the router.
  * controller by the router.
@@ -203,7 +205,8 @@ App.WizardStep7Controller = Em.Controller.extend({
         sender: this,
         sender: this,
         data: {
         data: {
           serviceName: serviceName,
           serviceName: serviceName,
-          serviceConfigsDef: App.config.get('preDefinedServiceConfigs').findProperty('serviceName', serviceName)
+          serviceConfigsDef: App.config.get('preDefinedServiceConfigs').findProperty('serviceName', serviceName),
+          urlParams: ',hosts'
         },
         },
         success: 'loadServiceTagsSuccess'
         success: 'loadServiceTagsSuccess'
       });
       });
@@ -290,7 +293,7 @@ App.WizardStep7Controller = Em.Controller.extend({
       name: App.Service.DisplayNames[serviceName] + " Default",
       name: App.Service.DisplayNames[serviceName] + " Default",
       description: "Default cluster level " + serviceName + " configuration",
       description: "Default cluster level " + serviceName + " configuration",
       isDefault: true,
       isDefault: true,
-      hosts: defaultConfigGroupHosts,
+      hosts: [],
       parentConfigGroup: null,
       parentConfigGroup: null,
       service: Em.Object.create({
       service: Em.Object.create({
         id: serviceName
         id: serviceName
@@ -300,9 +303,25 @@ App.WizardStep7Controller = Em.Controller.extend({
     });
     });
     if (!selectedConfigGroup) {
     if (!selectedConfigGroup) {
       selectedConfigGroup = defaultConfigGroup;
       selectedConfigGroup = defaultConfigGroup;
+      lazyLoading.run({
+        initSize: 20,
+        chunkSize: 50,
+        delay: 200,
+        destination: selectedConfigGroup.get('hosts'),
+        source: defaultConfigGroupHosts,
+        context: Em.Object.create()
+      });
     }
     }
     configGroups = configGroups.sortProperty('name');
     configGroups = configGroups.sortProperty('name');
     configGroups.unshift(defaultConfigGroup);
     configGroups.unshift(defaultConfigGroup);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 200,
+      destination: configGroups.objectAt(0).get('hosts'),
+      source: defaultConfigGroupHosts,
+      context: Em.Object.create()
+    });
     if (App.get('supports.hostOverrides')) {
     if (App.get('supports.hostOverrides')) {
       service.set('configGroups', configGroups);
       service.set('configGroups', configGroups);
       var loadedGroupToOverrideSiteToTagMap = {};
       var loadedGroupToOverrideSiteToTagMap = {};
@@ -696,7 +715,14 @@ App.WizardStep7Controller = Em.Controller.extend({
     var installedServiceSites = [];
     var installedServiceSites = [];
     this.get('serviceConfigsData').filter(function (service) {
     this.get('serviceConfigsData').filter(function (service) {
       if (this.get('installedServiceNames').contains(service.serviceName)) {
       if (this.get('installedServiceNames').contains(service.serviceName)) {
-        installedServiceSites = installedServiceSites.concat(service.sites);
+        lazyLoading.run({
+          initSize: 20,
+          chunkSize: 50,
+          delay: 50,
+          destination: installedServiceSites,
+          source: service.sites,
+          context: Em.Object.create()
+        });
       }
       }
     }, this);
     }, this);
     installedServiceSites = installedServiceSites.uniq();
     installedServiceSites = installedServiceSites.uniq();
@@ -781,7 +807,7 @@ App.WizardStep7Controller = Em.Controller.extend({
    */
    */
   loadConfigGroups: function (serviceConfigGroups) {
   loadConfigGroups: function (serviceConfigGroups) {
     var services = this.get('stepConfigs');
     var services = this.get('stepConfigs');
-    var hosts = this.get('wizardController.allHosts').mapProperty('hostName');
+    var hosts = Em.keys(this.get('wizardController').getDBProperty('hosts'));
     services.forEach(function (service) {
     services.forEach(function (service) {
       if (service.get('serviceName') === 'MISC') return;
       if (service.get('serviceName') === 'MISC') return;
       var serviceRawGroups = serviceConfigGroups.filterProperty('service.id', service.serviceName);
       var serviceRawGroups = serviceConfigGroups.filterProperty('service.id', service.serviceName);
@@ -791,13 +817,21 @@ App.WizardStep7Controller = Em.Controller.extend({
             name: App.Service.DisplayNames[service.serviceName] + " Default",
             name: App.Service.DisplayNames[service.serviceName] + " Default",
             description: "Default cluster level " + service.serviceName + " configuration",
             description: "Default cluster level " + service.serviceName + " configuration",
             isDefault: true,
             isDefault: true,
-            hosts: Em.copy(hosts),
+            hosts: [],
             service: Em.Object.create({
             service: Em.Object.create({
               id: service.serviceName
               id: service.serviceName
             }),
             }),
             serviceName: service.serviceName
             serviceName: service.serviceName
           })
           })
         ]);
         ]);
+        lazyLoading.run({
+          initSize: 20,
+          chunkSize: 50,
+          delay: 50,
+          destination: service.get('configGroups').objectAt(0).get('hosts'),
+          source: hosts,
+          context: Em.Object.create()
+        });
       }
       }
       else {
       else {
         var defaultGroup = App.ConfigGroup.create(serviceRawGroups.findProperty('isDefault'));
         var defaultGroup = App.ConfigGroup.create(serviceRawGroups.findProperty('isDefault'));

+ 0 - 5
ambari-web/app/styles/application.less

@@ -756,11 +756,6 @@ h1 {
       background-color: #808080;
       background-color: #808080;
       opacity: 0.2;
       opacity: 0.2;
     }
     }
-    .spinner {
-      position: absolute;
-      margin-top: 30%;
-      margin-left: 50%;
-    }
   }
   }
   #deploy {
   #deploy {
     .pre-scrollable {
     .pre-scrollable {

+ 27 - 23
ambari-web/app/templates/wizard/step10.hbs

@@ -25,29 +25,33 @@
 <div class="alert alert-info">
 <div class="alert alert-info">
   {{t installer.step10.body}}
   {{t installer.step10.body}}
 </div>
 </div>
-<div id="step10-content" class="well pre-scrollable">
-  <ul>
-    {{#each item in clusterInfo}}
-      <li>
-        <span {{bindAttr class="item.color"}}>{{item.displayStatement}}</span>
-        <ul>
-          {{#each status in item.status}}
-            <li>
-              <span {{bindAttr class="status.color"}}>{{status.displayStatement}}</span>
-              <ul>
-                {{#each statement in status.statements}}
-                  <li>
-                    <span {{bindAttr class="status.color"}}>{{statement.displayStatement}}</span>
-                  </li>
-                {{/each}}
-              </ul>
-            </li>
-          {{/each}}
-        </ul>
-      </li>
-    {{/each}}
-  </ul>
-</div>
+{{#if controller.isLoaded}}
+  <div id="step10-content" class="well pre-scrollable">
+    <ul>
+      {{#each item in clusterInfo}}
+        <li>
+          <span {{bindAttr class="item.color"}}>{{item.displayStatement}}</span>
+          <ul>
+            {{#each status in item.status}}
+              <li>
+                <span {{bindAttr class="status.color"}}>{{status.displayStatement}}</span>
+                <ul>
+                  {{#each statement in status.statements}}
+                    <li>
+                      <span {{bindAttr class="status.color"}}>{{statement.displayStatement}}</span>
+                    </li>
+                  {{/each}}
+                </ul>
+              </li>
+            {{/each}}
+          </ul>
+        </li>
+      {{/each}}
+    </ul>
+  </div>
+{{else}}
+  <div class="spinner"></div>
+{{/if}}
 <div class="btn-area">
 <div class="btn-area">
   <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action complete}}>{{t common.complete}} &rarr;</a>
   <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action complete}}>{{t common.complete}} &rarr;</a>
 </div>
 </div>

+ 133 - 117
ambari-web/app/templates/wizard/step3.hbs

@@ -21,133 +21,149 @@
 
 
   <p class="alert alert-info">{{t installer.step3.body}}</p>
   <p class="alert alert-info">{{t installer.step3.body}}</p>
 
 
-  <div class="box">
-    <div class="box-header">
-      <div class="button-section">
-        <button class="btn btn-primary" {{bindAttr disabled="view.noHostsSelected"}}
-          {{action removeSelectedHosts target="controller" }}><i class="icon-trash icon-white"></i>
-          {{t installer.step3.removeSelected}}
-        </button>
-        {{#unless isRetryDisabled}}
-          <a class="btn btn-primary decommission"
-             href="#" {{action retrySelectedHosts target="view"}}><i class="icon-repeat icon-white"></i>
-            {{t installer.step3.retryFailed}}
-          </a>
-        {{/unless}}
+  {{#if view.isLoaded}}
+    {{#if controller.isLoaded}}
 
 
-        <div id="host-filter" class="pull-right">
-          <ul class="clearfix">
-            <li class="first">{{t common.show}}:</li>
-            {{#each category in view.categories}}
-              <li {{bindAttr class=":filter-status category.itemClass"}}>
-                <a {{action selectCategory category target="view"}} href="#">
-                  {{category.label}}
-                </a>
-              </li>
-              {{#unless category.last}}
-                <li class="divider">|</li>
-              {{/unless}}
-            {{/each}}
-          </ul>
+      <div class="box">
+        <div class="box-header">
+          <div class="button-section">
+            <button class="btn btn-primary" {{bindAttr disabled="view.noHostsSelected"}}
+              {{action removeSelectedHosts target="controller" }}><i class="icon-trash icon-white"></i>
+              {{t installer.step3.removeSelected}}
+            </button>
+            {{#unless isRetryDisabled}}
+              <a class="btn btn-primary decommission"
+                 href="#" {{action retrySelectedHosts target="view"}}><i class="icon-repeat icon-white"></i>
+                {{t installer.step3.retryFailed}}
+              </a>
+            {{/unless}}
+
+            <div id="host-filter" class="pull-right">
+              <ul class="clearfix">
+                <li class="first">{{t common.show}}:</li>
+                {{#each category in view.categories}}
+                  <li {{bindAttr class=":filter-status category.itemClass"}}>
+                    <a {{action selectCategory category target="view"}} href="#">
+                      {{category.label}}
+                    </a>
+                  </li>
+                  {{#unless category.last}}
+                    <li class="divider">|</li>
+                  {{/unless}}
+                {{/each}}
+              </ul>
+            </div>
+          </div>
         </div>
         </div>
-      </div>
-    </div>
 
 
-    <div class="pre-scrollable" style="max-height: 440px;">
-      <table class="table table-bordered table-striped">
-        <thead>
-        <tr>
-          <th class="tinyspan">
-            {{view Ember.Checkbox checkedBinding="view.pageChecked"}}
-          </th>
-          <th class="span5">{{t common.host}}</th>
-          <!-- retrieved from local storage initially -->
-          <th class="span2">{{t common.progress}}</th>
-          <th class="span2">{{t common.status}}</th>
-          <!-- given by the parsing function that parses data from bootstrap call, dynamically assign the color -->
-          <th class="span2">{{t common.action}}</th>
-          <!-- trash icon -->
-          <!-- retry icon -->
-        </tr>
-        </thead>
-        <tbody>
-          {{#if view.pageContent}}
-            {{#each host in view.pageContent}}
-              {{#view App.WizardHostView categoryBinding="controller.category" hostInfoBinding="host"}}
-              <td>
-                {{view Ember.Checkbox checkedBinding="host.isChecked"}}
-              </td>
-              <td>
-                {{host.name}}
-              </td>
-              <td>
-                <div {{bindAttr class="host.bootBarColor host.isBootDone::progress-striped host.isBootDone::active :progress"}}>
-                  <div class="bar" style="width:100%">
-                  </div>
-                </div>
-              </td>
-              <td>
-                <a href="javascript:void(null)"
-                   data-toggle="modal" {{action hostLogPopup host target="controller"}}><span {{bindAttr class="host.bootStatusColor"}}>{{host.bootStatusForDisplay}}</span></a>
-              </td>
-              <td>
-                <a class="btn btn-mini" {{action remove target="view"}}><i class="icon-trash"></i>
-                  {{t common.remove}}</a>
-                {{#if view.isRetryable}}<a class="btn btn-mini" {{action retry target="view"}}><i
-                    class="icon-repeat"></i>
-                  {{t common.retry}}</a>{{/if}}
-              </td>
-              {{/view}}
-            {{/each}}
-          {{else}}
-          <tr>
-            <td colspan="5">
-              {{t hosts.table.noHosts}}
-            </td>
-          </tr>
-          {{/if}}
-        </tbody>
-      </table>
-    </div>
-    <div id="hosts">
-      <div class="page-bar">
-        <div class="selected-hosts-info pull-left">
-          {{#if view.selectedHostsCount}}
-            <a {{action selectedHostsPopup target="controller"}} href="#">
-              {{view.selectedHostsCount}}
-              {{pluralize view.selectedHostsCount singular="t:hosts.filters.selectedHostInfo" plural="t:hosts.filters.selectedHostsInfo"}}
-            </a>
-            -
-            <a {{action unSelectAll target="view"}} href="#">{{t hosts.filters.clearSelection}}</a>
-          {{/if}}
+        <div class="pre-scrollable" style="max-height: 440px;">
+          <table class="table table-bordered table-striped">
+            <thead>
+            <tr>
+              <th class="tinyspan">
+                {{view Ember.Checkbox checkedBinding="view.pageChecked"}}
+              </th>
+              <th class="span5">{{t common.host}}</th>
+              <!-- retrieved from local storage initially -->
+              <th class="span2">{{t common.progress}}</th>
+              <th class="span2">{{t common.status}}</th>
+              <!-- given by the parsing function that parses data from bootstrap call, dynamically assign the color -->
+              <th class="span2">{{t common.action}}</th>
+              <!-- trash icon -->
+              <!-- retry icon -->
+            </tr>
+            </thead>
+            <tbody>
+            {{#if view.pageContent}}
+              {{#each host in view.pageContent}}
+                {{#view App.WizardHostView categoryBinding="controller.category" hostInfoBinding="host"}}
+                  <td>
+                    {{view Ember.Checkbox checkedBinding="host.isChecked"}}
+                  </td>
+                  <td>
+                    {{host.name}}
+                  </td>
+                  <td>
+                    <div {{bindAttr class="host.bootBarColor host.isBootDone::progress-striped host.isBootDone::active :progress"}}>
+                      <div class="bar" style="width:100%">
+                      </div>
+                    </div>
+                  </td>
+                  <td>
+                    <a href="javascript:void(null)"
+                       data-toggle="modal" {{action hostLogPopup host target="controller"}}><span {{bindAttr class="host.bootStatusColor"}}>{{host.bootStatusForDisplay}}</span></a>
+                  </td>
+                  <td>
+                    <a class="btn btn-mini" {{action remove target="view"}}><i class="icon-trash"></i>
+                      {{t common.remove}}</a>
+                    {{#if view.isRetryable}}<a class="btn btn-mini" {{action retry target="view"}}><i
+                      class="icon-repeat"></i>
+                      {{t common.retry}}</a>{{/if}}
+                  </td>
+                {{/view}}
+              {{/each}}
+            {{else}}
+              <tr>
+                <td colspan="5">
+                  {{t hosts.table.noHosts}}
+                </td>
+              </tr>
+            {{/if}}
+            </tbody>
+          </table>
         </div>
         </div>
-        <div class="items-on-page">
-          <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+        <div id="hosts">
+          <div class="page-bar">
+            <div class="selected-hosts-info pull-left">
+              {{#if view.selectedHostsCount}}
+                <a {{action selectedHostsPopup target="controller"}} href="#">
+                  {{view.selectedHostsCount}}
+                  {{pluralize view.selectedHostsCount singular="t:hosts.filters.selectedHostInfo" plural="t:hosts.filters.selectedHostsInfo"}}
+                </a>
+                -
+                <a {{action unSelectAll target="view"}} href="#">{{t hosts.filters.clearSelection}}</a>
+              {{/if}}
+            </div>
+            <div class="items-on-page">
+              <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+            </div>
+            <div class="info">{{view.paginationInfo}}</div>
+            <div class="paging_two_button">
+              {{view view.paginationFirst}}
+              {{view view.paginationLeft}}
+              {{view view.paginationRight}}
+              {{view view.paginationLast}}
+            </div>
+          </div>
         </div>
         </div>
-        <div class="info">{{view.paginationInfo}}</div>
-        <div class="paging_two_button">
-          {{view view.paginationFirst}}
-          {{view view.paginationLeft}}
-          {{view view.paginationRight}}
-          {{view view.paginationLast}}
+      </div>
+      {{#if hasMoreRegisteredHosts}}
+        <div {{bindAttr class=":alert alert-warn"}}>
+          <a href="#" {{action registeredHostsPopup target="controller"}}>{{controller.registeredHostsMessage}}</a>
         </div>
         </div>
+      {{/if}}
+      <div {{bindAttr class=":alert view.status isWarningsBoxVisible::hidden"}}>
+        {{view.message}}
+        <a href="#" {{action hostWarningsPopup warnings target="controller"}}>{{view.linkText}}</a>
+        {{#unless isWarningsLoaded}}
+          <div class="spinner"></div>
+        {{/unless}}
       </div>
       </div>
-    </div>
-  </div>
-  {{#if hasMoreRegisteredHosts}}
-    <div {{bindAttr class=":alert alert-warn"}}>
-      <a href="#" {{action registeredHostsPopup target="controller"}}>{{view.registeredHostsMessage}}</a>
-    </div>
-  {{/if}}
-  <div {{bindAttr class=":alert view.status isWarningsBoxVisible::hidden"}}>
-    {{view.message}}
-    <a href="#" {{action hostWarningsPopup warnings target="controller"}}>{{view.linkText}}</a>
-    {{#unless isWarningsLoaded}}
+
+    {{else}}
+
       <div class="spinner"></div>
       <div class="spinner"></div>
-    {{/unless}}
-  </div>
+
+    {{/if}}
+  {{else}}
+
+    <div class="spinner"></div>
+
+  {{/if}}
+
   <div class="btn-area">
   <div class="btn-area">
     <button class="btn pull-left" {{bindAttr disabled="isRegistrationInProgress"}} {{action back}}>&larr; {{t common.back}}</button>
     <button class="btn pull-left" {{bindAttr disabled="isRegistrationInProgress"}} {{action back}}>&larr; {{t common.back}}</button>
     <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
     <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
   </div>
   </div>
+
 </div>
 </div>

+ 66 - 62
ambari-web/app/templates/wizard/step5.hbs

@@ -24,43 +24,44 @@
     {{t installer.step5.body.hive}}
     {{t installer.step5.body.hive}}
   {{/if}}
   {{/if}}
 </div>
 </div>
-<div class="assign-masters row-fluid">
-  <div class="select-hosts span7">
-    <div class="row-fluid">
-      {{#if showCurrentHost}}
-        <div class="span12 control-group mlc">
-          <div class="row-fluid">
-            <div class="span4"><span class="pull-right control-label">{{t services.reassign.step2.currentHost}}</span>
+{{#if controller.isLoaded}}
+  <div class="assign-masters row-fluid">
+    <div class="select-hosts span7">
+      <div class="row-fluid">
+        {{#if showCurrentHost}}
+          <div class="span12 control-group mlc">
+            <div class="row-fluid">
+              <div class="span4"><span class="pull-right control-label">{{t services.reassign.step2.currentHost}}</span>
+              </div>
+              <div class="span8"><span>{{currentHostId}}</span></div>
             </div>
             </div>
-            <div class="span8"><span>{{currentHostId}}</span></div>
           </div>
           </div>
-        </div>
-      {{/if}}
-      <div class="clearfix"></div>
-      <div class="row-fluid">
-        <div class="span12 control-group">
-          <form class="form-horizontal" autocomplete="off">
-            <!-- View for array controller -->
-            {{#each servicesMasters}}
-              <div class="row-fluid">
-                <div class="span4">
-                  <div class="control-group">
-                    <label class="pts pull-right">
-                      {{#if controller.isReassignHive}}
-                        {{t installer.step5.hiveGroup}}
-                      {{else}}
-                        {{display_name}}:
-                      {{/if}}
-                    </label>
-                  </div>
-                </div>
-                <div class="span8">
-                  {{#if isHiveCoHost}}
-                    <div class="hostName">
-                      {{selectedHost}}<i class="icon-asterisks">&#10037;</i>
+        {{/if}}
+        <div class="clearfix"></div>
+        <div class="row-fluid">
+          <div class="span12 control-group">
+            <form class="form-horizontal" autocomplete="off">
+              <!-- View for array controller -->
+              {{#each servicesMasters}}
+                <div class="row-fluid">
+                  <div class="span4">
+                    <div class="control-group">
+                      <label class="pts pull-right">
+                        {{#if controller.isReassignHive}}
+                          {{t installer.step5.hiveGroup}}
+                        {{else}}
+                          {{display_name}}:
+                        {{/if}}
+                      </label>
                     </div>
                     </div>
-                  {{else}}
-                    {{view App.SelectHostView
+                  </div>
+                  <div class="span8">
+                    {{#if isHiveCoHost}}
+                      <div class="hostName">
+                        {{selectedHost}}<i class="icon-asterisks">&#10037;</i>
+                      </div>
+                    {{else}}
+                      {{view App.SelectHostView
                       optionValuePath="content.host_name"
                       optionValuePath="content.host_name"
                       optionLabelPath="content.host_info"
                       optionLabelPath="content.host_info"
                       selectedHostBinding="selectedHost"
                       selectedHostBinding="selectedHost"
@@ -68,41 +69,44 @@
                       class="host-select"
                       class="host-select"
                       zIdBinding="zId"
                       zIdBinding="zId"
                       disabledBinding="isInstalled"
                       disabledBinding="isInstalled"
-                    }}
-                    {{#if showAddControl}}
-                      {{view App.AddControlView componentNameBinding="component_name"}}
-                    {{/if}}
-                    {{#if showRemoveControl}}
-                      {{view App.RemoveControlView componentNameBinding="component_name" zIdBinding="zId"}}
+                      }}
+                      {{#if showAddControl}}
+                        {{view App.AddControlView componentNameBinding="component_name"}}
+                      {{/if}}
+                      {{#if showRemoveControl}}
+                        {{view App.RemoveControlView componentNameBinding="component_name" zIdBinding="zId"}}
+                      {{/if}}
                     {{/if}}
                     {{/if}}
-                  {{/if}}
+                  </div>
                 </div>
                 </div>
-              </div>
-            {{/each}}
-          </form>
+              {{/each}}
+            </form>
+          </div>
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
-  </div>
 
 
-  <div class="host-assignments span5">
-    {{#each masterHostMapping}}
-      <div class="mapping-box round-corners well">
-        <div class="hostString"><span>{{hostInfo}}</span></div>
-        {{#each masterServices}}
-          <span {{bindAttr class="isInstalled:assignedService:newService :round-corners"}}>{{display_name}}</span>
-        {{/each}}
-      </div>
-    {{/each}}
+    <div class="host-assignments span5">
+      {{#each masterHostMapping}}
+        <div class="mapping-box round-corners well">
+          <div class="hostString"><span>{{hostInfo}}</span></div>
+          {{#each masterServices}}
+            <span {{bindAttr class="isInstalled:assignedService:newService :round-corners"}}>{{display_name}}</span>
+          {{/each}}
+        </div>
+      {{/each}}
 
 
-    {{#if remainingHosts}}
-      <div class="remaining-hosts round-corners well">
-        <span><strong>{{remainingHosts}}</strong> {{t installer.step5.attention}}</span></div>
-    {{/if}}
+      {{#if remainingHosts}}
+        <div class="remaining-hosts round-corners well">
+          <span><strong>{{remainingHosts}}</strong> {{t installer.step5.attention}}</span></div>
+      {{/if}}
+    </div>
+    <div class="clearfix"></div>
   </div>
   </div>
-  <div class="clearfix"></div>
-</div>
+{{else}}
+  <div class="spinner"></div>
+{{/if}}
 <div class="btn-area">
 <div class="btn-area">
   <a class="btn pull-left" {{action back href="true"}}>&larr; {{t common.back}}</a>
   <a class="btn pull-left" {{action back href="true"}}>&larr; {{t common.back}}</a>
-  <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</a>
-</div>
+  <a class="btn btn-success pull-right" {{bindAttr disabled="submitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</a>
+</div>

+ 58 - 51
ambari-web/app/templates/wizard/step6.hbs

@@ -22,62 +22,69 @@
   {{#if errorMessage}}
   {{#if errorMessage}}
     <div class="alert alert-error">{{errorMessage}}</div>
     <div class="alert alert-error">{{errorMessage}}</div>
   {{/if}}
   {{/if}}
+  {{#if controller.isLoaded}}
+    {{#if view.isLoaded}}
+      <div class="pre-scrollable">
+        <table class="table table-striped" id="component_assign_table">
+          <thead>
+          <tr>
+            <th>{{t common.host}}</th>
+            {{#each header in controller.headers}}
 
 
-  <div class="pre-scrollable">
-    <table class="table table-striped" id="component_assign_table">
-      <thead>
-        <tr>
-          <th>{{t common.host}}</th>
-          {{#each header in controller.headers}}
-
-            <th>
-              <a href="#" {{bindAttr class="header.allChecked:selected:deselected"}}
-                {{action "selectAllNodes" header target="controller"}}>{{t all}}</a>&nbsp;|&nbsp;<a href="#" {{bindAttr class="header.noChecked:selected:deselected"}}
+              <th>
+                <a href="#" {{bindAttr class="header.allChecked:selected:deselected"}}
+                  {{action "selectAllNodes" header target="controller"}}>{{t all}}</a>&nbsp;|&nbsp;<a href="#" {{bindAttr class="header.noChecked:selected:deselected"}}
                 {{action "deselectAllNodes" header target="controller"}}>{{t none}}</a>
                 {{action "deselectAllNodes" header target="controller"}}>{{t none}}</a>
-            </th>
+              </th>
 
 
-          {{/each}}
-        </tr>
-      </thead>
-      <tbody>
-        {{#if view.pageContent}}
-          {{#each host in view.pageContent}}
-            <tr>
-              {{#view App.WizardStep6HostView hostBinding="host" }}
-                {{host.hostName}}
-                {{#if host.hasMaster}}
-                  <i class=icon-asterisks>&#10037;</i>
-                {{/if}}
-              {{/view}}
-              {{#each checkbox in host.checkboxes}}
-                <td>
-                  <label class="checkbox">
-                    {{#view view.checkboxView checkboxBinding="checkbox"}}
-                      {{checkbox.title}}
-                    {{/view}}
-                  </label>
-                </td>
-              {{/each}}
-            </tr>
-          {{/each}}
-        {{/if}}
-      </tbody>
-    </table>
-  </div>
-  <div id="hosts">
-    <div class="page-bar">
-      <div class="items-on-page">
-        <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+            {{/each}}
+          </tr>
+          </thead>
+          <tbody>
+          {{#if view.pageContent}}
+            {{#each host in view.pageContent}}
+              <tr>
+                {{#view App.WizardStep6HostView hostBinding="host" }}
+                  {{host.hostName}}
+                  {{#if host.hasMaster}}
+                    <i class=icon-asterisks>&#10037;</i>
+                  {{/if}}
+                {{/view}}
+                {{#each checkbox in host.checkboxes}}
+                  <td>
+                    <label class="checkbox">
+                      {{#view view.checkboxView checkboxBinding="checkbox"}}
+                        {{checkbox.title}}
+                      {{/view}}
+                    </label>
+                  </td>
+                {{/each}}
+              </tr>
+            {{/each}}
+          {{/if}}
+          </tbody>
+        </table>
       </div>
       </div>
-      <div class="info">{{view.paginationInfo}}</div>
-      <div class="paging_two_button">
-        {{view view.paginationFirst}}
-        {{view view.paginationLeft}}
-        {{view view.paginationRight}}
-        {{view view.paginationLast}}
+      <div id="hosts">
+        <div class="page-bar">
+          <div class="items-on-page">
+            <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+          </div>
+          <div class="info">{{view.paginationInfo}}</div>
+          <div class="paging_two_button">
+            {{view view.paginationFirst}}
+            {{view view.paginationLeft}}
+            {{view view.paginationRight}}
+            {{view view.paginationLast}}
+          </div>
+        </div>
       </div>
       </div>
-    </div>
-  </div>
+    {{else}}
+      <div class="spinner"></div>
+    {{/if}}
+  {{else}}
+    <div class="spinner"></div>
+  {{/if}}
   <div class="btn-area">
   <div class="btn-area">
     <a class="btn" {{action back}}>&larr; {{t common.back}}</a>
     <a class="btn" {{action back}}>&larr; {{t common.back}}</a>
     <a class="btn btn-success pull-right" {{action next}}>{{t common.next}} &rarr;</a>
     <a class="btn btn-success pull-right" {{action next}}>{{t common.next}} &rarr;</a>

+ 117 - 109
ambari-web/app/templates/wizard/step9.hbs

@@ -22,123 +22,131 @@
 
 
   <p class="alert alert-info">{{t installer.step9.body}}</p>
   <p class="alert alert-info">{{t installer.step9.body}}</p>
 
 
-  <div id="overallProgress">
-    <div class="row-fluid">
-      <div class="span10">
-        <div {{bindAttr class="view.isStepCompleted::progress-striped view.isStepCompleted::active view.barColor :progress"}}>
-          <div class="bar" {{bindAttr style="view.barWidth"}}>
-          </div>
-        </div>
-      </div>
-      <div class="span2">{{view.progressMessage}}</div>
-    </div>
-  </div>
-
-  <div class="box">
-    <div class="box-header">
-      <div class="pull-left">
-        {{#if controller.showRetry}}
-          <a class="btn btn-primary" href="#" {{action retry}}>
-            <i class="icon-repeat icon-white"></i>
-            {{t common.retry}}
-          </a>
-        {{/if}}
-      </div>
-      <!-- filter by host level -->
-      <div id="host-filter" class="pull-right">
-        <ul class="clearfix">
-          <li class="first">{{t common.show}}:</li>
-          {{#each category in view.categories}}
-            <li {{bindAttr class=":filter-status category.itemClass"}}>
-              <a {{action selectCategory category target="view"}} href="#">
-                {{category.label}}
-              </a>
-            </li>
-            {{#unless category.last}}
-              <li class="divider">|</li>
-            {{/unless}}
-          {{/each}}
-        </ul>
-      </div>
-    </div>
-    <div class="pre-scrollable">
-      <table id="deploy-status-by-host" class="table table-bordered table-striped">
-        <thead>
-        <tr>
-          <th class="host">
-            {{t common.host}}
-          </th>
-          <th class="status">{{t common.status}}</th>
-          <!--  given by the parsing function that parses data from bootstrap call -->
-          <th class="message">{{t common.message}}</th>
-          <!-- retrieved from local storage initially -->
-        </tr>
-        </thead>
+  {{#if view.isLoaded}}
 
 
-        <tbody>
-          {{#if view.pageContent}}
-            {{#each host in view.pageContent}}
-              {{#view App.HostStatusView objBinding="host" controllerBinding="controller"}}
-              <td>
-                {{host.name}}
-              </td>
-              <td>
-                <div class="progress-bar pull-left">
-                  <div {{bindAttr class="view.isHostCompleted::progress-striped view.isHostCompleted::active view.barColor :progress"}}>
-                    <div class="bar" {{bindAttr style="view.barWidth"}}></div>
-                  </div>
+    <div id="overallProgress">
+        <div class="row-fluid">
+            <div class="span10">
+                <div {{bindAttr class="view.isStepCompleted::progress-striped view.isStepCompleted::active view.barColor :progress"}}>
+                    <div class="bar" {{bindAttr style="view.barWidth"}}>
+                    </div>
                 </div>
                 </div>
-                <div class="progress-percentage pull-left">{{host.progress}}%</div>
-              </td>
-              <td>
-                <a {{bindAttr class="view.isFailed:text-error view.isSuccess:text-success view.isWarning:text-warning"}}
-                    href="javascript:void(null)"
-                    data-toggle="modal" {{action hostLogPopup target="view"}}>{{host.message}}</a>
-              </td>
-              {{/view}}
-            {{/each}}
-          {{else}}
-          <tr>
-            <td colspan="3"><p>{{t installer.step3.hosts.noHosts}}</p></td>
-          </tr>
-          {{/if}}
-        </tbody>
-      </table>
+            </div>
+            <div class="span2">{{view.progressMessage}}</div>
+        </div>
     </div>
     </div>
-    <div id="hosts">
-      <div class="page-bar">
-        <div class="selected-hosts-info pull-left">
-          {{view.filteredHostsInfo}}
-          -
-          <a {{action showAllHosts target="view"}} href="#">{{t tableView.filters.showAll}}</a>
+
+    <div class="box">
+        <div class="box-header">
+            <div class="pull-left">
+              {{#if controller.showRetry}}
+                  <a class="btn btn-primary" href="#" {{action retry}}>
+                      <i class="icon-repeat icon-white"></i>
+                    {{t common.retry}}
+                  </a>
+              {{/if}}
+            </div>
+            <!-- filter by host level -->
+            <div id="host-filter" class="pull-right">
+                <ul class="clearfix">
+                    <li class="first">{{t common.show}}:</li>
+                  {{#each category in view.categories}}
+                      <li {{bindAttr class=":filter-status category.itemClass"}}>
+                          <a {{action selectCategory category target="view"}} href="#">
+                            {{category.label}}
+                          </a>
+                      </li>
+                    {{#unless category.last}}
+                        <li class="divider">|</li>
+                    {{/unless}}
+                  {{/each}}
+                </ul>
+            </div>
         </div>
         </div>
-        <div class="items-on-page">
-          <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+        <div class="pre-scrollable">
+            <table id="deploy-status-by-host" class="table table-bordered table-striped">
+                <thead>
+                <tr>
+                    <th class="host">
+                      {{t common.host}}
+                    </th>
+                    <th class="status">{{t common.status}}</th>
+                    <!--  given by the parsing function that parses data from bootstrap call -->
+                    <th class="message">{{t common.message}}</th>
+                    <!-- retrieved from local storage initially -->
+                </tr>
+                </thead>
+
+                <tbody>
+                {{#if view.pageContent}}
+                  {{#each host in view.pageContent}}
+                    {{#view App.HostStatusView objBinding="host" controllerBinding="controller"}}
+                        <td>
+                          {{host.name}}
+                        </td>
+                        <td>
+                            <div class="progress-bar pull-left">
+                                <div {{bindAttr class="view.isHostCompleted::progress-striped view.isHostCompleted::active view.barColor :progress"}}>
+                                    <div class="bar" {{bindAttr style="view.barWidth"}}></div>
+                                </div>
+                            </div>
+                            <div class="progress-percentage pull-left">{{host.progress}}%</div>
+                        </td>
+                        <td>
+                            <a {{bindAttr class="view.isFailed:text-error view.isSuccess:text-success view.isWarning:text-warning"}}
+                                    href="javascript:void(null)"
+                                    data-toggle="modal" {{action hostLogPopup target="view"}}>{{host.message}}</a>
+                        </td>
+                    {{/view}}
+                  {{/each}}
+                {{else}}
+                    <tr>
+                        <td colspan="3"><p>{{t installer.step3.hosts.noHosts}}</p></td>
+                    </tr>
+                {{/if}}
+                </tbody>
+            </table>
         </div>
         </div>
-        <div class="info">{{view.paginationInfo}}</div>
-        <div class="paging_two_button">
-          {{view view.paginationFirst}}
-          {{view view.paginationLeft}}
-          {{view view.paginationRight}}
-          {{view view.paginationLast}}
+        <div id="hosts">
+            <div class="page-bar">
+                <div class="selected-hosts-info pull-left">
+                  {{view.filteredHostsInfo}}
+                    -
+                    <a {{action showAllHosts target="view"}} href="#">{{t tableView.filters.showAll}}</a>
+                </div>
+                <div class="items-on-page">
+                    <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+                </div>
+                <div class="info">{{view.paginationInfo}}</div>
+                <div class="paging_two_button">
+                  {{view view.paginationFirst}}
+                  {{view view.paginationLeft}}
+                  {{view view.paginationRight}}
+                  {{view view.paginationLast}}
+                </div>
+            </div>
         </div>
         </div>
-      </div>
     </div>
     </div>
-  </div>
 
 
-  <div>
-    {{#if view.resultMsg}}
-      <p {{bindAttr class="view.resultMsgColor :alert"}}>{{view.resultMsg}}
-        {{#if view.isHostHeartbeatLost}}
-          <a href="javascript:void(null)"
-             data-toggle="modal" {{action hostWithInstallFailed target="view"}}>{{t common.showDetails}}</a>
-        {{/if}}
-      </p>
-    {{/if}}
-    <div class="btn-area">
-      <button
-          class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
+    <div>
+      {{#if view.resultMsg}}
+          <p {{bindAttr class="view.resultMsgColor :alert"}}>{{view.resultMsg}}
+            {{#if view.isHostHeartbeatLost}}
+                <a href="javascript:void(null)"
+                   data-toggle="modal" {{action hostWithInstallFailed target="view"}}>{{t common.showDetails}}</a>
+            {{/if}}
+          </p>
+      {{/if}}
+        <div class="btn-area">
+            <button
+                    class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
+        </div>
     </div>
     </div>
-  </div>
+
+  {{else}}
+
+    <div class="spinner"></div>
+
+  {{/if}}
 
 
 </div>
 </div>

+ 9 - 1
ambari-web/app/utils/ajax/ajax.js

@@ -2135,8 +2135,12 @@ var urls = {
     'real': '/clusters/{clusterName}/hosts?fields=Hosts/public_host_name&minimal_response=true',
     'real': '/clusters/{clusterName}/hosts?fields=Hosts/public_host_name&minimal_response=true',
     'mock': ''
     'mock': ''
   },
   },
+  'hosts.confirmed.install': {
+    'real': '/hosts?fields=Hosts/cpu_count,Hosts/disk_info,Hosts/total_mem&minimal_response=true',
+    'mock': ''
+  },
   'hosts.confirmed': {
   'hosts.confirmed': {
-    'real': '/clusters/{clusterName}/hosts?fields=Hosts/cpu_count,Hosts/disk_info,Hosts/total_mem&minimal_response=true',
+    'real': '/clusters/{clusterName}/hosts?fields=Hosts/cpu_count,Hosts/disk_info,Hosts/total_mem,host_components&minimal_response=true',
     'mock': ''
     'mock': ''
   },
   },
   'host_components.all': {
   'host_components.all': {
@@ -2147,6 +2151,10 @@ var urls = {
     'real': '/clusters/{clusterName}/host_components?fields=component/ServiceComponentInfo/service_name,HostRoles/host_name&minimal_response=true',
     'real': '/clusters/{clusterName}/host_components?fields=component/ServiceComponentInfo/service_name,HostRoles/host_name&minimal_response=true',
     'mock': ''
     'mock': ''
   },
   },
+  'components.get_installed': {
+    'real': '/clusters/{clusterName}/components',
+    'mock': ''
+  },
   'hosts.heatmaps': {
   'hosts.heatmaps': {
     'real': '/clusters/{clusterName}/hosts?fields=Hosts/host_name,Hosts/maintenance_state,Hosts/public_host_name,Hosts/cpu_count,Hosts/ph_cpu_count,Hosts/total_mem,Hosts/host_status,Hosts/last_heartbeat_time,Hosts/os_arch,Hosts/os_type,Hosts/ip,host_components/HostRoles/state,host_components/HostRoles/maintenance_state,Hosts/disk_info,metrics/disk,metrics/load/load_one,metrics/cpu/cpu_system,metrics/cpu/cpu_user,metrics/memory/mem_total,metrics/memory/mem_free,alerts/summary&minimal_response=true',
     'real': '/clusters/{clusterName}/hosts?fields=Hosts/host_name,Hosts/maintenance_state,Hosts/public_host_name,Hosts/cpu_count,Hosts/ph_cpu_count,Hosts/total_mem,Hosts/host_status,Hosts/last_heartbeat_time,Hosts/os_arch,Hosts/os_type,Hosts/ip,host_components/HostRoles/state,host_components/HostRoles/maintenance_state,Hosts/disk_info,metrics/disk,metrics/load/load_one,metrics/cpu/cpu_system,metrics/cpu/cpu_user,metrics/memory/mem_total,metrics/memory/mem_free,alerts/summary&minimal_response=true',
     'mock': ''
     'mock': ''

+ 26 - 0
ambari-web/app/views/main/host/add_view.js

@@ -53,6 +53,32 @@ App.AddHostView = Em.View.extend({
 
 
  isStepDisabled: function (index) {
  isStepDisabled: function (index) {
     return this.get('controller.isStepDisabled').findProperty('step', index).get('value');
     return this.get('controller.isStepDisabled').findProperty('step', index).get('value');
+  },
+
+  didInsertElement: function () {
+    App.ajax.send({
+      name: 'hosts.confirmed',
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName')
+      },
+      success: 'loadConfirmedHostsSuccessCallback'
+    });
+  },
+
+  loadConfirmedHostsSuccessCallback: function (response) {
+    var hosts = {};
+    response.items.mapProperty('Hosts').forEach(function(item){
+      hosts[item.host_name] = {
+        name: item.host_name,
+        cpu: item.cpu_count,
+        memory: item.total_mem,
+        disk_info: item.disk_info,
+        bootStatus: "REGISTERED",
+        isInstalled: true
+      };
+    });
+    this.get('controller').setDBProperty('hosts', hosts);
   }
   }
 
 
 });
 });

+ 26 - 0
ambari-web/app/views/main/service/add_view.js

@@ -53,6 +53,32 @@ App.AddServiceView = Em.View.extend({
 
 
   isStepDisabled: function (index) {
   isStepDisabled: function (index) {
     return this.get('controller.isStepDisabled').findProperty('step', index).get('value');
     return this.get('controller.isStepDisabled').findProperty('step', index).get('value');
+  },
+
+  didInsertElement: function () {
+    App.ajax.send({
+      name: 'hosts.confirmed',
+      sender: this,
+      data: {
+        clusterName: App.get('clusterName')
+      },
+      success: 'loadConfirmedHostsSuccessCallback'
+    });
+  },
+
+  loadConfirmedHostsSuccessCallback: function (response) {
+    var hosts = {};
+    response.items.mapProperty('Hosts').forEach(function(item){
+      hosts[item.host_name] = {
+        name: item.host_name,
+        cpu: item.cpu_count,
+        memory: item.total_mem,
+        disk_info: item.disk_info,
+        bootStatus: "REGISTERED",
+        isInstalled: true
+      };
+    });
+    this.get('controller').setDBProperty('hosts', hosts);
   }
   }
 
 
 });
 });

+ 16 - 17
ambari-web/app/views/wizard/step3_view.js

@@ -18,6 +18,7 @@
 
 
 
 
 var App = require('app');
 var App = require('app');
+var lazyLoading = require('utils/lazy_loading');
 
 
 App.WizardStep3View = App.TableView.extend({
 App.WizardStep3View = App.TableView.extend({
 
 
@@ -28,9 +29,19 @@ App.WizardStep3View = App.TableView.extend({
    * Same to <code>controller.hosts</code>
    * Same to <code>controller.hosts</code>
    * @type {Ember.Enumerable}
    * @type {Ember.Enumerable}
    */
    */
-  content:function () {
-    return this.get('controller.hosts');
-  }.property('controller.hosts.length'),
+  content: [],
+
+  contentObserver: function() {
+    this.set('content', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content'),
+      source: this.get('controller.hosts'),
+      context: this
+    });
+  }.observes('controller.hosts.length'),
 
 
   /**
   /**
    * Message with info about registration result
    * Message with info about registration result
@@ -58,12 +69,6 @@ App.WizardStep3View = App.TableView.extend({
     return this.get('categories').findProperty('isActive');
     return this.get('categories').findProperty('isActive');
   }.property('categories.@each.isActive'),
   }.property('categories.@each.isActive'),
 
 
-  /**
-   * Message about other registered hosts (not included in current registration)
-   * @type {string}
-   */
-  registeredHostsMessage: '',
-
   /**
   /**
    * Number of visible hosts on page
    * Number of visible hosts on page
    * @type {string}
    * @type {string}
@@ -76,6 +81,8 @@ App.WizardStep3View = App.TableView.extend({
    */
    */
   pageChecked: false,
   pageChecked: false,
 
 
+  isLoaded: false,
+
   /**
   /**
    * bootStatus category object
    * bootStatus category object
    * @type {Ember.Object}
    * @type {Ember.Object}
@@ -165,14 +172,6 @@ App.WizardStep3View = App.TableView.extend({
     this.set('selectedHostsCount', selectedHostsCount);
     this.set('selectedHostsCount', selectedHostsCount);
   },
   },
 
 
-  /**
-   * Update <code>registeredHostsMessage</code> according to <code>controller.registeredHots.length</code>
-   * @method setRegisteredHosts
-   */
-  setRegisteredHosts: function(){
-    this.set('registeredHostsMessage',Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('controller.registeredHosts').length));
-  }.observes('controller.registeredHosts'),
-
   /**
   /**
    * Call filters and counters one time
    * Call filters and counters one time
    * @method hostBootStatusObserver
    * @method hostBootStatusObserver

+ 14 - 3
ambari-web/app/views/wizard/step6_view.js

@@ -18,6 +18,7 @@
 
 
 
 
 var App = require('app');
 var App = require('app');
+var lazyLoading = require('utils/lazy_loading');
 
 
 App.WizardStep6View = App.TableView.extend({
 App.WizardStep6View = App.TableView.extend({
 
 
@@ -35,9 +36,19 @@ App.WizardStep6View = App.TableView.extend({
    * List of hosts
    * List of hosts
    * @type {object[]}
    * @type {object[]}
    */
    */
-  content: function () {
-    return this.get('controller.hosts');
-  }.property('controller.hosts'),
+  content: [],
+
+  contentObserver: function() {
+    this.set('content', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content'),
+      source: this.get('controller.hosts'),
+      context: this
+    });
+  }.observes('controller.hosts.length'),
 
 
   /**
   /**
    * Synonym to <code>content</code> in this <code>App.TableView</code>
    * Synonym to <code>content</code> in this <code>App.TableView</code>

+ 16 - 3
ambari-web/app/views/wizard/step9_view.js

@@ -18,6 +18,7 @@
 
 
 var App = require('app');
 var App = require('app');
 var date = require('utils/date');
 var date = require('utils/date');
+var lazyLoading = require('utils/lazy_loading');
 
 
 App.WizardStep9View = App.TableView.extend({
 App.WizardStep9View = App.TableView.extend({
 
 
@@ -55,13 +56,25 @@ App.WizardStep9View = App.TableView.extend({
    */
    */
   displayLength: "25",
   displayLength: "25",
 
 
+  isLoaded: false,
+
   /**
   /**
    * Same to <code>controller.hosts</code>
    * Same to <code>controller.hosts</code>
    * @type {object[]}
    * @type {object[]}
    */
    */
-  content: function () {
-    return this.get('controller.hosts');
-  }.property('controller.hosts'),
+  content: [],
+
+  contentObserver: function() {
+    this.set('content', []);
+    lazyLoading.run({
+      initSize: 20,
+      chunkSize: 50,
+      delay: 50,
+      destination: this.get('content'),
+      source: this.get('controller.hosts'),
+      context: this
+    });
+  }.observes('controller.hosts.length'),
 
 
   /**
   /**
    * Active category
    * Active category