Browse Source

AMBARI-10116 Use all host components in recommendations. (ababiichuk)

aBabiichuk 10 years ago
parent
commit
e11724985b

+ 1 - 1
ambari-web/app/controllers/global/update_controller.js

@@ -459,7 +459,7 @@ App.UpdateController = Em.Controller.extend({
   updateComponentsState: function (callback) {
     var testUrl = '/data/services/HDP2/components_state.json';
     var realUrl = '/components/?ServiceComponentInfo/category.in(SLAVE,CLIENT)&fields=ServiceComponentInfo/service_name,' +
-      'ServiceComponentInfo/category,ServiceComponentInfo/installed_count,ServiceComponentInfo/started_count,ServiceComponentInfo/total_count&minimal_response=true';
+      'ServiceComponentInfo/category,ServiceComponentInfo/installed_count,ServiceComponentInfo/started_count,ServiceComponentInfo/total_count,host_components/HostRoles/host_name&minimal_response=true';
     var url = this.getUrl(testUrl, realUrl);
 
     App.HttpClient.get(url, App.componentsStateMapper, {

+ 4 - 12
ambari-web/app/controllers/main/service/info/configs.js

@@ -41,7 +41,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
   configGroups: [],
   allConfigs: [],
   uiConfigs: [],
-  customConfig: [],
   isApplyingChanges: false,
   saveConfigsFlag: true,
   isCompareMode: false,
@@ -75,9 +74,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
   serviceConfigs: function () {
     return App.config.get('preDefinedServiceConfigs');
   }.property('App.config.preDefinedServiceConfigs'),
-  customConfigs: function () {
-    return App.config.get('preDefinedCustomConfigs');
-  }.property('App.config.preDefinedCustomConfigs'),
+
   configMapping: function () {
     return App.config.get('configMapping');
   }.property('App.config.configMapping'),
@@ -225,7 +222,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
     this.get('stepConfigs').clear();
     this.get('allConfigs').clear();
     this.get('uiConfigs').clear();
-    this.get('customConfig').clear();
     this.set('loadedGroupToOverrideSiteToTagMap', {});
     this.set('serviceConfigVersionNote', '');
     this.set('savedSiteNameToServerServiceConfigDataMap', {});
@@ -574,8 +570,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
       configSet = App.config.syncOrderWithPredefined(configSet);
 
       var configs = configSet.configs;
-      //add custom configs
-      App.config.addCustomConfigs(configs);
       //put properties from capacity-scheduler.xml into one config with textarea view
       if (self.get('content.serviceName') === 'YARN') {
         configs = App.config.fileConfigsIntoTextarea(configs, 'capacity-scheduler.xml');
@@ -735,7 +729,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
   /**
    * init attributes and wrap mock compare config into App.ServiceConfigProperty
    * @param serviceConfig
-   * @param compareConfig
+   * @param compareServiceVersion
    * @return {object}
    */
   getMockComparisonConfig: function (serviceConfig, compareServiceVersion) {
@@ -982,10 +976,9 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
    * @method loadConfigs
    */
   loadConfigs: function (configs, componentConfig) {
-    var serviceConfigsData = App.StackService.find().findProperty('serviceName', this.get('content.serviceName'));
     var defaultGroupSelected = this.get('selectedConfigGroup.isDefault');
     configs.forEach(function (_serviceConfigProperty) {
-      var serviceConfigProperty = this.createConfigProperty(_serviceConfigProperty, defaultGroupSelected, serviceConfigsData);
+      var serviceConfigProperty = this.createConfigProperty(_serviceConfigProperty, defaultGroupSelected);
       componentConfig.configs.pushObject(serviceConfigProperty);
       serviceConfigProperty.validate();
     }, this);
@@ -996,11 +989,10 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
    * create {Em.Object} service_cfg_property based on {Object}_serviceConfigProperty and additional info
    * @param {Object} _serviceConfigProperty - config object
    * @param {Boolean} defaultGroupSelected - true if selected cfg group is default
-   * @param {Object} serviceConfigsData - service cfg object
    * @returns {Ember.Object|null}
    * @method createConfigProperty
    */
-  createConfigProperty: function (_serviceConfigProperty, defaultGroupSelected, serviceConfigsData) {
+  createConfigProperty: function (_serviceConfigProperty, defaultGroupSelected) {
     if (!_serviceConfigProperty) return null;
 
     var overrides = _serviceConfigProperty.overrides;

+ 0 - 2
ambari-web/app/controllers/wizard/step7_controller.js

@@ -591,8 +591,6 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
     App.config.setPreDefinedServiceConfigs(this.get('addMiscTabToPage'));
     //STEP 4: Add advanced configs
     App.config.addAdvancedConfigs(configs, advancedConfigs);
-    //STEP 5: Add custom configs
-    App.config.addCustomConfigs(configs);
 
     this.set('groupsToDelete', this.get('wizardController').getDBProperty('groupsToDelete') || []);
 

+ 4 - 1
ambari-web/app/mappers/components_state_mapper.js

@@ -31,7 +31,8 @@ App.componentsStateMapper = App.QuickDataMapper.create({
     service_name: 'ServiceComponentInfo.service_name',
     installed_count: 'ServiceComponentInfo.installed_count',
     started_count: 'ServiceComponentInfo.started_count',
-    total_count: 'ServiceComponentInfo.total_count'
+    total_count: 'ServiceComponentInfo.total_count',
+    host_names: 'host_names'
   },
 
   slaveModel: App.SlaveComponent,
@@ -145,10 +146,12 @@ App.componentsStateMapper = App.QuickDataMapper.create({
         var cacheService = App.cache['services'].findProperty('ServiceInfo.service_name', item.ServiceComponentInfo.service_name);
 
         if (item.ServiceComponentInfo.category === 'CLIENT') {
+          item.host_names = item.host_components.mapProperty('HostRoles.host_name');
           clients.push(this.parseIt(item, this.clientMap));
         }
         if (item.ServiceComponentInfo.category === 'SLAVE') {
           // for now map for slaves and clients are equal but it may vary in future.
+          item.host_names = item.host_components.mapProperty('HostRoles.host_name');
           slaves.push(this.parseIt(item, this.clientMap));
         }
 

+ 30 - 28
ambari-web/app/mixins/common/serverValidator.js

@@ -22,17 +22,26 @@ var blueprintUtils = require('utils/blueprint');
 App.ServerValidatorMixin = Em.Mixin.create({
 
   /**
-   * @type {bool} set true if at leasst one config has error
+   * defines if we use validation and recommendation on wizards
+   * depend on this flag some properties will be taken from different places
+   * @type {boolean}
+   */
+  isWizard: function() {
+    return this.get('wizardController') && ['addServiceController' || 'installerController'].contains(this.get('wizardController.name'));
+  }.property('wizardController.name'),
+
+  /**
+   * @type {boolean} set true if at least one config has error
    */
   configValidationError: false,
 
   /**
-   * @type {bool} set true if at leasst one config has warning
+   * @type {boolean} set true if at least one config has warning
    */
   configValidationWarning: false,
 
   /**
-   * @type {bool} set true if at leasst one config has warning
+   * @type {boolean} set true if at least one config has warning
    */
   configValidationFailed: false,
 
@@ -55,19 +64,21 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @type {Object}
    */
   hostNames: function() {
-    return this.get('content.hosts')
+    return this.get('isWizard')
         ? Object.keys(this.get('content.hosts'))
         : App.get('allHostNames');
-  }.property('content.hosts', 'App.allHostNames'),
+  }.property('isWizard', 'content.hosts', 'App.allHostNames'),
 
-  allHostNames: [],
   /**
    * by default loads data from model otherwise must be overridden as computed property
    * @type {Array} - of strings (serviceNames)
    */
   serviceNames: function() {
-    return this.get('content.serviceName') ? [this.get('content.serviceName')] : this.get('allSelectedServiceNames');
-  }.property('content.serviceName', 'allSelectedServiceNames.@each'),
+    // When editing a service we validate only that service's configs.
+    // However, we should pass the IDs of services installed, or else,
+    // default value calculations will alter.
+    return this.get('isWizard') ? this.get('allSelectedServiceNames') : App.Service.find().mapProperty('serviceName');
+  }.property('isWizard', 'allSelectedServiceNames'),
 
   /**
    * by default loads data from model otherwise must be overridden as computed property
@@ -75,12 +86,11 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @type {Array} - of objects (services)
    */
   services: function() {
-    return this.get('content.serviceName')
-        ? [App.StackService.find(this.get('content.serviceName'))]
-        : this.get('content.services').filter(function(s){
-          return (s.get('isSelected') || s.get('isInstalled'));
-        }).concat(require("data/service_configs"));
-  }.property('content.serviceName', 'content.services', 'content.services.@each.isSelected', 'content.services.@each.isInstalled', 'content.stacks.@each.isSelected'),
+    var stackServices = App.StackService.find().filter(function(s) {
+      return this.get('serviceNames').contains(s.get('serviceName'));
+    }, this);
+    return this.get('isWizard') ? stackServices.concat(require("data/service_configs")) : stackServices;
+  }.property('serviceNames'),
 
   /**
    * by default loads data from model otherwise must be overridden as computed property
@@ -88,18 +98,18 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @type {Array} of strings (hostNames)
    */
   hostGroups: function() {
-    return this.get('content.recommendationsHostGroups') || blueprintUtils.generateHostGroups(this.get('hostNames'), App.HostComponent.find());
-  }.property('content.recommendationsHostGroups', 'hostNames'),
+    return this.get('content.recommendationsHostGroups') || blueprintUtils.generateHostGroups(App.get('allHostNames'));
+  }.property('content.recommendationsHostGroups', 'App.allHostNames'),
 
   /**
-   * controller that is child of this mixis has to contain stepConfigs
+   * controller that is child of this mixin has to contain stepConfigs
    * @type {Array}
    */
   stepConfigs: null,
 
   /**
    * @method loadServerSideConfigsRecommendations
-   * laod recommendations from server
+   * load recommendations from server
    * (used only during install)
    * @returns {*}
    */
@@ -159,15 +169,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
   runServerSideValidation: function(deferred) {
     var self = this;
     var recommendations = this.get('hostGroups');
-    recommendations.blueprint.configurations = blueprintUtils.buildConfisJSON(this.get('services'), this.get('stepConfigs'));
-
-    var serviceNames = this.get('serviceNames');
-    if (!self.get('isInstaller')) {
-      // When editing a service we validate only that service's configs.
-      // However, we should pass the IDs of services installed, or else,
-      // default value calculations will alter.
-      serviceNames = App.Service.find().mapProperty('serviceName');
-    }
+    recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(this.get('services'), this.get('stepConfigs'));
 
     return App.ajax.send({
       name: 'config.validations',
@@ -175,7 +177,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
       data: {
         stackVersionUrl: App.get('stackVersionURL'),
         hosts: this.get('hostNames'),
-        services: serviceNames,
+        services: this.get('serviceNames'),
         validate: 'configurations',
         recommendations: recommendations
       },

+ 2 - 0
ambari-web/app/models/client_component.js

@@ -26,6 +26,8 @@ App.ClientComponent = DS.Model.extend({
   startedCount: DS.attr('number'),
   totalCount: DS.attr('number'),
   stackInfo: DS.belongsTo('App.StackServiceComponent'),
+  hostNames: DS.attr('array'),
+
 
   displayName: function() {
     var displayName = App.format.role(this.get('componentName'));

+ 0 - 1
ambari-web/app/models/service_config.js

@@ -191,7 +191,6 @@ App.ServiceConfigProperty = Em.Object.extend({
   restartRequiredMessage: 'Restart required',
   index: null, //sequence number in category
   editDone: false, //Text field: on focusOut: true, on focusIn: false
-  serviceValidator: null,
   isNotSaved: false, // user property was added but not saved
   hasInitialValue: false, //if true then property value is defined and saved to server
   isHiddenByFilter: false, //if true then hide this property (filtered out)

+ 22 - 5
ambari-web/app/utils/blueprint.js

@@ -190,7 +190,7 @@ module.exports = {
   },
 
   /**
-   * @method buildConfisJSON - generet JSON according to blueprint format
+   * @method buildConfigsJSON - generates JSON according to blueprint format
    * @param {Em.Array} stepConfigs - array of Ember Objects
    * @param {Array} services
    * @returns {Object}
@@ -210,7 +210,7 @@ module.exports = {
    *   }
    * }
    */
-  buildConfisJSON: function(services, stepConfigs) {
+  buildConfigsJSON: function(services, stepConfigs) {
     var configurations = {};
     services.forEach(function(service) {
       var config = stepConfigs.findProperty('serviceName', service.get('serviceName'));
@@ -237,10 +237,9 @@ module.exports = {
   /**
    * @method generateHostGroups
    * @param {Array} hostNames - list of all hostNames
-   * @param {Array} hostComponents - list of all hostComponents
    * @returns {{blueprint: {host_groups: Array}, blueprint_cluster_binding: {host_groups: Array}}}
    */
-  generateHostGroups: function(hostNames, hostComponents) {
+  generateHostGroups: function(hostNames) {
     var recommendations = {
       blueprint: {
         host_groups: []
@@ -255,7 +254,7 @@ module.exports = {
         name: "host-group-" + i,
         components: []
       };
-      var hcFiltered = hostComponents.filterProperty('hostName', hostNames[i-1]).mapProperty('componentName');
+      var hcFiltered = this.getComponentForHost(hostNames[i-1]);
       for (var j = 0; j < hcFiltered.length; j++) {
         host_group.components.push({
           name: hcFiltered[j]
@@ -270,5 +269,23 @@ module.exports = {
       });
     }
     return recommendations;
+  },
+
+  /**
+   * gets all component names that are present on current host
+   * @param {String} hostName
+   * @returns {Array}
+   */
+  getComponentForHost: function(hostName) {
+    var clients = App.ClientComponent.find().filter(function(c) {
+      return c.get('hostNames').contains(hostName);
+    }).mapProperty('componentName');
+    var slaves = App.SlaveComponent.find().filter(function(s) {
+      return s.get('hostNames').contains(hostName);
+    }).mapProperty('componentName');
+    var masters = App.HostComponent.find().filter(function(m) {
+      return m.get('isMaster') && m.get('hostName') === hostName;
+    }).mapProperty('componentName');
+    return masters.concat(slaves).concat(clients);
   }
 };

+ 24 - 36
ambari-web/app/utils/config.js

@@ -122,18 +122,13 @@ App.config = Em.Object.create({
     return require('data/HDP2/site_properties').configProperties;
   }.property('App.isHadoop22Stack', 'App.currentStackName'),
 
-  preDefinedCustomConfigs: require('data/HDP2/custom_configs'),
-
-  preDefinedConfigFile: function (file) {
+  preDefinedConfigFile: function(file) {
     try {
       return require('data/{0}/{1}'.format(App.get('currentStackName'), file));
     } catch (err) {
       // the file doesn't exist, which might be expected.
     }
   },
-  //categories which contain custom configs
-  categoriesWithCustom: ['CapacityScheduler'],
-
 
   /**
    * Create array of service properties for Log4j files
@@ -181,7 +176,7 @@ App.config = Em.Object.create({
    * @param siteNames {String|Array}
    * @returns {Array}
    */
-  getBySitename: function (siteNames) {
+  getBySiteName: function (siteNames) {
     var computedConfigs = this.get('configMapping').computed();
     var siteProperties = [];
     if (typeof siteNames === "string") {
@@ -354,7 +349,7 @@ App.config = Em.Object.create({
         }
 
         this.tweakConfigVisibility(serviceConfigObj, properties);
-        if (!this.getBySitename(serviceConfigObj.get('filename')).someProperty('name', index)) {
+        if (!this.getBySiteName(serviceConfigObj.get('filename')).someProperty('name', index)) {
           if (configsPropertyDef) {
             if (configsPropertyDef.isRequiredByAgent === false) {
               continue;
@@ -629,15 +624,6 @@ App.config = Em.Object.create({
       }, this);
     }
   },
-  /**
-   * Render a custom conf-site box for entering properties that will be written in *-site.xml files of the services
-   */
-  addCustomConfigs: function (configs) {
-    var preDefinedCustomConfigs = $.extend(true, [], this.get('preDefinedCustomConfigs'));
-    var stored = configs.filter(function (_config) {
-      return this.get('categoriesWithCustom').contains(_config.category);
-    }, this);
-  },
 
   miscConfigVisibleProperty: function (configs, serviceToShow) {
     configs.forEach(function (item) {
@@ -1002,27 +988,29 @@ App.config = Em.Object.create({
       'zk_user': 'ZooKeeper User',
       'ignore_groupsusers_create': 'Skip group modifications during install'
     };
-    if (config.property_type.contains('USER') || config.property_type.contains('GROUP')) {
-      propertyData.id = "puppet var";
-      propertyData.category = 'Users and Groups';
-      propertyData.isVisible = !App.get('isHadoopWindowsStack');
-      propertyData.serviceName = 'MISC';
-      propertyData.isOverridable = false;
-      propertyData.isReconfigurable = false;
-      propertyData.displayName = nameToDisplayNameMap[config.property_name] || App.format.normalizeName(config.property_name);
-      propertyData.displayType = config.property_name == 'ignore_groupsusers_create' ? 'checkbox' : 'user';
-      if (config.service_name) {
-        var propertyIndex = config.service_name == 'MISC' ? 30 : App.StackService.find().mapProperty('serviceName').indexOf(config.service_name);
-        propertyData.belongsToService = [config.service_name];
-        propertyData.index = propertyIndex;
-      } else {
-        propertyData.index = 30;
+    if (Em.isArray(config.property_type)) {
+      if (config.property_type.contains('USER') || config.property_type.contains('GROUP')) {
+        propertyData.id = "puppet var";
+        propertyData.category = 'Users and Groups';
+        propertyData.isVisible = !App.get('isHadoopWindowsStack');
+        propertyData.serviceName = 'MISC';
+        propertyData.isOverridable = false;
+        propertyData.isReconfigurable = false;
+        propertyData.displayName = nameToDisplayNameMap[config.property_name] || App.format.normalizeName(config.property_name);
+        propertyData.displayType = config.property_name == 'ignore_groupsusers_create' ? 'checkbox' : 'user';
+        if (config.service_name) {
+          var propertyIndex = config.service_name == 'MISC' ? 30 : App.StackService.find().mapProperty('serviceName').indexOf(config.service_name);
+          propertyData.belongsToService = [config.service_name];
+          propertyData.index = propertyIndex;
+        } else {
+          propertyData.index = 30;
+        }
+        if (config.property_name == 'proxyuser_group') propertyData.belongsToService = proxyUserGroupServices;
       }
-      if (config.property_name == 'proxyuser_group') propertyData.belongsToService = proxyUserGroupServices;
-    }
 
-    if (config.property_type.contains('PASSWORD')) {
-      propertyData.displayType = "password";
+      if (config.property_type.contains('PASSWORD')) {
+        propertyData.displayType = "password";
+      }
     }
 
     return propertyData;

+ 0 - 3
ambari-web/test/controllers/wizard/step7_test.js

@@ -1047,7 +1047,6 @@ describe('App.InstallerStep7Controller', function () {
       });
       sinon.stub(App.config, 'mergePreDefinedWithStored', Em.K);
       sinon.stub(App.config, 'addAdvancedConfigs', Em.K);
-      sinon.stub(App.config, 'addCustomConfigs', Em.K);
       sinon.stub(App.config, 'fileConfigsIntoTextarea', Em.K);
       sinon.stub(installerStep7Controller, 'clearStep', Em.K);
       sinon.stub(installerStep7Controller, 'getConfigTags', Em.K);
@@ -1063,7 +1062,6 @@ describe('App.InstallerStep7Controller', function () {
     afterEach(function () {
       App.config.mergePreDefinedWithStored.restore();
       App.config.addAdvancedConfigs.restore();
-      App.config.addCustomConfigs.restore();
       App.config.fileConfigsIntoTextarea.restore();
       installerStep7Controller.clearStep.restore();
       installerStep7Controller.getConfigTags.restore();
@@ -1089,7 +1087,6 @@ describe('App.InstallerStep7Controller', function () {
       installerStep7Controller.loadStep();
       expect(App.config.mergePreDefinedWithStored.calledOnce).to.equal(true);
       expect(App.config.addAdvancedConfigs.calledOnce).to.equal(true);
-      expect(App.config.addCustomConfigs.calledOnce).to.equal(true);
     });
     it('should call setInstalledServiceConfigs for addServiceController', function () {
       installerStep7Controller.set('wizardController.name', 'addServiceController');

+ 11 - 3
ambari-web/test/utils/blueprint_test.js

@@ -277,7 +277,7 @@ describe('utils/blueprint', function() {
     });
   });
 
-  describe('#buildConfisJSON', function () {
+  describe('#buildConfigsJSON', function () {
     var tests = [
       {
         "services": [
@@ -329,12 +329,20 @@ describe('utils/blueprint', function() {
     ];
     tests.forEach(function (test) {
       it("generate configs for request (use in validation)", function () {
-        expect(blueprintUtils.buildConfisJSON(test.services, test.stepConfigs)).to.eql(test.configurations);
+        expect(blueprintUtils.buildConfigsJSON(test.services, test.stepConfigs)).to.eql(test.configurations);
       });
     });
   });
 
   describe('#generateHostGroups', function () {
+    beforeEach(function() {
+      sinon.stub(blueprintUtils, 'getComponentForHost' ,function(host) {
+        return host == "host1" ? ["C1","C2"] : ["C1","C3"];
+      });
+    });
+    afterEach(function() {
+      blueprintUtils.getComponentForHost.restore();
+    })
     var tests = [
       {
         "hostNames": ["host1", "host2"],
@@ -408,7 +416,7 @@ describe('utils/blueprint', function() {
     ];
     tests.forEach(function (test) {
       it("generate host groups", function () {
-        expect(blueprintUtils.generateHostGroups(test.hostNames, test.hostComponents)).to.eql(test.result);
+        expect(blueprintUtils.generateHostGroups(test.hostNames)).to.eql(test.result);
       });
     });
   });