Browse Source

AMBARI-5389. Stack service component data should be dynamically fetched from server. (jaimin)

Jaimin Jetly 11 years ago
parent
commit
29e61ae9cf
28 changed files with 1240 additions and 786 deletions
  1. 51 47
      ambari-web/app/app.js
  2. 665 0
      ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json
  3. 87 58
      ambari-web/app/controllers/global/cluster_controller.js
  4. 17 4
      ambari-web/app/controllers/installer.js
  5. 9 11
      ambari-web/app/controllers/main/host/add_controller.js
  6. 5 5
      ambari-web/app/controllers/main/service/add_controller.js
  7. 0 1
      ambari-web/app/controllers/main/service/item.js
  8. 1 2
      ambari-web/app/controllers/main/service/manage_config_groups_controller.js
  9. 26 12
      ambari-web/app/controllers/wizard.js
  10. 28 34
      ambari-web/app/controllers/wizard/step5_controller.js
  11. 2 3
      ambari-web/app/controllers/wizard/step6_controller.js
  12. 3 3
      ambari-web/app/controllers/wizard/step7_controller.js
  13. 3 4
      ambari-web/app/controllers/wizard/step8_controller.js
  14. 2 3
      ambari-web/app/controllers/wizard/step9_controller.js
  15. 86 120
      ambari-web/app/data/HDP2/global_properties.js
  16. 0 423
      ambari-web/app/data/service_components.js
  17. 2 14
      ambari-web/app/initialize.js
  18. 34 0
      ambari-web/app/mappers.js
  19. 44 0
      ambari-web/app/mappers/stack_service_component_mapper.js
  20. 1 0
      ambari-web/app/models.js
  21. 72 0
      ambari-web/app/models/stack_service_component.js
  22. 4 4
      ambari-web/app/utils/ajax.js
  23. 28 0
      ambari-web/app/utils/component.js
  24. 1 1
      ambari-web/app/views/main/host/summary.js
  25. 6 35
      ambari-web/test/app_test.js
  26. 0 1
      ambari-web/test/installer/step5_test.js
  27. 3 1
      ambari-web/test/installer/step6_test.js
  28. 60 0
      ambari-web/test/installer/step9_test.js

+ 51 - 47
ambari-web/app/app.js

@@ -91,7 +91,6 @@ module.exports = Em.Application.create({
    *    for example:
    *      properties: { global_properties: [], site_properties: [], etc. }
    *   @property reviewConfigs {Ember.Object} - reference review_configs.js
-   *   @property serviceComponent {Object} - reference service_components.js
    *
    * @type {Array}
    */
@@ -105,45 +104,42 @@ module.exports = Em.Application.create({
   enableComponent: function(component) {
     var propertyFileNames = ['global_properties', 'site_properties'];
     var requirePrefix = this.get('isHadoop2Stack') ? 'data/HDP2/' : 'data/';
-    // add component to service_components list
-    require('data/service_components').push(component.get('serviceComponent'));
     // add properties
     propertyFileNames.forEach(function(fileName) {
       require(requirePrefix + fileName).configProperties = require(requirePrefix + fileName).configProperties.concat(component.get('properties.'+fileName));
     });
     var reviewConfigsService = require('data/review_configs')
       .findProperty('config_name', 'services').config_value
-      .findProperty('service_name', component.get('serviceComponent.service_name'));
+      .findProperty('service_name', component.get('serviceName'));
     reviewConfigsService.get('service_components').pushObject(component.get('reviewConfigs'));
   },
   /**
    * Disabling component. Remove related data from lists such as
    * properties, review configs, service components.
    *
-   * @param component {Object} - component info reference service_components.js
+   * @param component {Object} - stack service component
    *
    * @return {Ember.Object} - item of <code>stackDependedComponents</code> property
    */
   disableComponent: function(component) {
     var componentCopy, propertyFileNames;
+    var service_configs = require('data/service_configs');
     propertyFileNames = ['global_properties', 'site_properties'];
     componentCopy = Em.Object.create({
-      componentName: component.component_name,
+      componentName: component.get('componentName'),
+      serviceName: component.get('serviceName'),
       properties: {},
       reviewConfigs: {},
-      configCategory: {},
-      serviceComponent: {}
+      configCategory: {}
     });
-    componentCopy.set('serviceComponent', require('data/service_components').findProperty('component_name', component.component_name));
-    // remove component from service_components list
-    require('data/service_components').removeObject(componentCopy.get('serviceComponent'));
+
     var serviceConfigsCategoryName, requirePrefix, serviceConfig;
     // get service category name related to component
-    serviceConfig = require('data/service_configs').findProperty('serviceName', component.service_name);
+    serviceConfig = service_configs.findProperty('serviceName', component.get('serviceName'));
     serviceConfig.configCategories = serviceConfig.configCategories.filter(function(configCategory) {
       if (configCategory.get('hostComponentNames')) {
         serviceConfigsCategoryName = configCategory.get('name');
-        if (configCategory.get('hostComponentNames').contains(component.component_name)) {
+        if (configCategory.get('hostComponentNames').contains(component.get('componentName'))) {
           componentCopy.set('configCategory', configCategory);
         }
       }
@@ -170,9 +166,9 @@ module.exports = Em.Application.create({
     // remove component from review configs
     var reviewConfigsService = require('data/review_configs')
       .findProperty('config_name', 'services').config_value
-      .findProperty('service_name', component.service_name);
+      .findProperty('service_name', component.get('serviceName'));
     reviewConfigsService.set('service_components', reviewConfigsService.get('service_components').filter(function (serviceComponent) {
-      if (serviceComponent.get('component_name') != component.component_name) {
+      if (serviceComponent.get('component_name') != component.get('componentName')) {
         return true;
       } else {
         componentCopy.set('reviewConfigs', serviceComponent);
@@ -188,51 +184,59 @@ module.exports = Em.Application.create({
   handleStackDependedComponents: function() {
     // need for unit testing and test mode
     if (this.get('handleStackDependencyTest') || this.testMode) return;
-    var stackVersion, stackDependedComponents;
-    stackVersion = this.get('currentStackVersionNumber');
-    stackDependedComponents = [];
+    var stackDependedComponents = [];
+    var service_configs = require('data/service_configs');
+    var stackServiceComponents = this.StackServiceComponent.find();
+    if (!stackServiceComponents.mapProperty('componentName').length) {
+       return;
+    }
     // disable components
-    require('data/service_components').filterProperty('stackVersions').forEach(function(component) {
-      if (!component.stackVersions.contains(stackVersion))
-        stackDependedComponents.push(this.disableComponent(component));
-    }, this);
+    service_configs.forEach(function(service){
+      service.configCategories.forEach(function(serviceConfigCategory){
+        var categoryComponents = serviceConfigCategory.get('hostComponentNames');
+        if (categoryComponents && categoryComponents.length) {
+          categoryComponents.forEach(function(categoryComponent) {
+            var stackComponent = stackServiceComponents.findProperty('componentName',categoryComponent);
+            if(!stackComponent && !this.get('stackDependedComponents').mapProperty('componentName').contains['categoryComponent'] ) {
+              var _stackComponent = Ember.Object.create({
+                componentName: categoryComponent,
+                serviceName:service.serviceName
+              });
+              stackDependedComponents.push(this.disableComponent(_stackComponent));
+            }
+          },this);
+        }
+      },this);
+    },this);
     // enable components
     if (this.get('stackDependedComponents').length > 0) {
       this.get('stackDependedComponents').forEach(function(component) {
-        if (component.get('serviceComponent').stackVersions.contains(this.get('currentStackVersionNumber'))) {
+        if (stackServiceComponents.findProperty('componentName',component.get('componentName'))) {
           this.enableComponent(component);
           stackDependedComponents = this.get('stackDependedComponents').removeObject(component);
         }
       }, this);
     }
     this.set('stackDependedComponents', this.get('stackDependedComponents').concat(stackDependedComponents));
-  }.observes('currentStackVersionNumber'),
+  },
 
   /**
    * List of components with allowed action for them
    * @type {Em.Object}
    */
-  components: Ember.Object.create({
-    reassignable: ['NAMENODE', 'SECONDARY_NAMENODE', 'JOBTRACKER', 'RESOURCEMANAGER'],
-    restartable: function() {
-      return this.get('masters').concat(this.get('slaves'));
-    }.property('masters'),
-    deletable: ['SUPERVISOR', 'HBASE_MASTER', 'DATANODE', 'TASKTRACKER', 'NODEMANAGER', 'HBASE_REGIONSERVER'],
-    rollinRestartAllowed: ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "SUPERVISOR"],
-    decommissionAllowed: ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER"],
-    addableToHost: ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "HBASE_MASTER", "ZOOKEEPER_SERVER", "SUPERVISOR"],
-    slaves: function() {
-      return require('data/service_components').filter(function(component){
-        return !component.isClient && !component.isMaster;
-      }).mapProperty('component_name').uniq().without("DASHBOARD").without("MYSQL_SERVER");
-    }.property().cacheable(),
-
-    masters: function() {
-      return require('data/service_components').filterProperty('isMaster', true)
-        .mapProperty('component_name').concat(['MYSQL_SERVER']).uniq();
-    }.property().cacheable(),
-    clients: function() {
-      return require('data/service_components').filterProperty('isClient', true).mapProperty('component_name').uniq();
-    }.property().cacheable()
-  })
+  components: function() {
+    var self = this;
+    return Ember.Object.create({
+      allComponents:self.StackServiceComponent.find().mapProperty('componentName'),
+      reassignable: self.StackServiceComponent.find().filterProperty('isReassignable',true).mapProperty('componentName'),
+      restartable: self.StackServiceComponent.find().filterProperty('isRestartable',true).mapProperty('componentName'),
+      deletable: self.StackServiceComponent.find().filterProperty('isDeletable',true).mapProperty('componentName'),
+      rollinRestartAllowed: self.StackServiceComponent.find().filterProperty('isRollinRestartAllowed',true).mapProperty('componentName'),
+      decommissionAllowed: self.StackServiceComponent.find().filterProperty('isDecommissionAllowed',true).mapProperty('componentName'),
+      addableToHost: self.StackServiceComponent.find().filterProperty('isAddableToHost',true).mapProperty('componentName'),
+      slaves: self.StackServiceComponent.find().filterProperty('isSlave',true).mapProperty('componentName'),
+      masters: self.StackServiceComponent.find().filterProperty('isMaster',true).mapProperty('componentName'),
+      clients: self.StackServiceComponent.find().filterProperty('isClient',true).mapProperty('componentName')
+    })
+  }.property()
 });

+ 665 - 0
ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json

@@ -0,0 +1,665 @@
+{
+  "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices?fields=StackServices/comments,StackServices/service_version,serviceComponents/*",
+  "items" : [
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/FALCON",
+      "StackServices" : {
+        "comments" : "Data management and processing platform",
+        "service_name" : "FALCON",
+        "service_version" : "0.4.0.2.1.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/FALCON/serviceComponents/FALCON_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "FALCON_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "FALCON",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/FALCON/serviceComponents/FALCON_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "FALCON_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "FALCON",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/GANGLIA",
+      "StackServices" : {
+        "comments" : "Ganglia Metrics Collection system",
+        "service_name" : "GANGLIA",
+        "service_version" : "3.5.0",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/GANGLIA/serviceComponents/GANGLIA_MONITOR",
+          "StackServiceComponents" : {
+            "component_category" : "SLAVE",
+            "component_name" : "GANGLIA_MONITOR",
+            "is_client" : false,
+            "is_master" : false,
+            "service_name" : "GANGLIA",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/GANGLIA/serviceComponents/GANGLIA_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "GANGLIA_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "GANGLIA",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HBASE",
+      "StackServices" : {
+        "comments" : "Non-relational distributed database and centralized service for configuration management &\n        synchronization\n      ",
+        "service_name" : "HBASE",
+        "service_version" : "0.96.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HBASE/serviceComponents/HBASE_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "HBASE_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "HBASE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HBASE/serviceComponents/HBASE_MASTER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "HBASE_MASTER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HBASE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HBASE/serviceComponents/HBASE_REGIONSERVER",
+          "StackServiceComponents" : {
+            "component_category" : "SLAVE",
+            "component_name" : "HBASE_REGIONSERVER",
+            "is_client" : false,
+            "is_master" : false,
+            "service_name" : "HBASE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HCATALOG",
+      "StackServices" : {
+        "comments" : "This is comment for HCATALOG service",
+        "service_name" : "HCATALOG",
+        "service_version" : "0.12.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HCATALOG/serviceComponents/HCAT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "HCAT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "HCATALOG",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS",
+      "StackServices" : {
+        "comments" : "Apache Hadoop Distributed File System",
+        "service_name" : "HDFS",
+        "service_version" : "2.1.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS/serviceComponents/DATANODE",
+          "StackServiceComponents" : {
+            "component_category" : "SLAVE",
+            "component_name" : "DATANODE",
+            "is_client" : false,
+            "is_master" : false,
+            "service_name" : "HDFS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS/serviceComponents/HDFS_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "HDFS_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "HDFS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS/serviceComponents/JOURNALNODE",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "JOURNALNODE",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HDFS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS/serviceComponents/NAMENODE",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "NAMENODE",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HDFS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS/serviceComponents/SECONDARY_NAMENODE",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "SECONDARY_NAMENODE",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HDFS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HDFS/serviceComponents/ZKFC",
+          "StackServiceComponents" : {
+            "component_category" : "SLAVE",
+            "component_name" : "ZKFC",
+            "is_client" : false,
+            "is_master" : false,
+            "service_name" : "HDFS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HIVE",
+      "StackServices" : {
+        "comments" : "Data warehouse system for ad-hoc queries & analysis of large datasets and table & storage management service",
+        "service_name" : "HIVE",
+        "service_version" : "0.12.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HIVE/serviceComponents/HIVE_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "HIVE_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "HIVE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HIVE/serviceComponents/HIVE_METASTORE",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "HIVE_METASTORE",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HIVE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HIVE/serviceComponents/HIVE_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "HIVE_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HIVE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/HIVE/serviceComponents/MYSQL_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "MYSQL_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "HIVE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/MAPREDUCE2",
+      "StackServices" : {
+        "comments" : "Apache Hadoop NextGen MapReduce (YARN)",
+        "service_name" : "MAPREDUCE2",
+        "service_version" : "2.1.0.2.0.6.0",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/MAPREDUCE2/serviceComponents/HISTORYSERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "HISTORYSERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "MAPREDUCE2",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/MAPREDUCE2/serviceComponents/MAPREDUCE2_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "MAPREDUCE2_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "MAPREDUCE2",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/NAGIOS",
+      "StackServices" : {
+        "comments" : "Nagios Monitoring and Alerting system",
+        "service_name" : "NAGIOS",
+        "service_version" : "3.5.0",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/NAGIOS/serviceComponents/NAGIOS_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "NAGIOS_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "NAGIOS",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/OOZIE",
+      "StackServices" : {
+        "comments" : "System for workflow coordination and execution of Apache Hadoop jobs.  This also includes the installation of the optional Oozie Web Console which relies on and will install the <a target=\"_blank\" href=\"http://www.sencha.com/products/extjs/license/\">ExtJS</a> Library.\n      ",
+        "service_name" : "OOZIE",
+        "service_version" : "4.0.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/OOZIE/serviceComponents/OOZIE_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "OOZIE_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "OOZIE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/OOZIE/serviceComponents/OOZIE_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "OOZIE_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "OOZIE",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/PIG",
+      "StackServices" : {
+        "comments" : "Scripting platform for analyzing large datasets",
+        "service_name" : "PIG",
+        "service_version" : "0.12.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/PIG/serviceComponents/PIG",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "PIG",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "PIG",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/SQOOP",
+      "StackServices" : {
+        "comments" : "Tool for transferring bulk data between Apache Hadoop and\n        structured data stores such as relational databases\n      ",
+        "service_name" : "SQOOP",
+        "service_version" : "1.4.4.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/SQOOP/serviceComponents/SQOOP",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "SQOOP",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "SQOOP",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM",
+      "StackServices" : {
+        "comments" : "Apache Hadoop Stream processing framework",
+        "service_name" : "STORM",
+        "service_version" : "0.9.0.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/DRPC_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "DRPC_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "STORM",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/LOGVIEWER_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "LOGVIEWER_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "STORM",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/NIMBUS",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "NIMBUS",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "STORM",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/STORM_REST_API",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "STORM_REST_API",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "STORM",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/STORM_UI_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "STORM_UI_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "STORM",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/SUPERVISOR",
+          "StackServiceComponents" : {
+            "component_category" : "SLAVE",
+            "component_name" : "SUPERVISOR",
+            "is_client" : false,
+            "is_master" : false,
+            "service_name" : "STORM",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/TEZ",
+      "StackServices" : {
+        "comments" : "Tez is the next generation Hadoop Query Processing framework written on top of YARN.",
+        "service_name" : "TEZ",
+        "service_version" : "0.4.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/TEZ/serviceComponents/TEZ_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "TEZ_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "TEZ",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/WEBHCAT",
+      "StackServices" : {
+        "comments" : "This is comment for WEBHCAT service",
+        "service_name" : "WEBHCAT",
+        "service_version" : "0.12.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/WEBHCAT/serviceComponents/WEBHCAT_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "WEBHCAT_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "WEBHCAT",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/YARN",
+      "StackServices" : {
+        "comments" : "Apache Hadoop NextGen MapReduce (YARN)",
+        "service_name" : "YARN",
+        "service_version" : "2.1.0.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/YARN/serviceComponents/APP_TIMELINE_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "APP_TIMELINE_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "YARN",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/YARN/serviceComponents/NODEMANAGER",
+          "StackServiceComponents" : {
+            "component_category" : "SLAVE",
+            "component_name" : "NODEMANAGER",
+            "is_client" : false,
+            "is_master" : false,
+            "service_name" : "YARN",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/YARN/serviceComponents/RESOURCEMANAGER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "RESOURCEMANAGER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "YARN",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/YARN/serviceComponents/YARN_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "YARN_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "YARN",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    },
+    {
+      "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/ZOOKEEPER",
+      "StackServices" : {
+        "comments" : "Centralized service which provides highly reliable distributed\n        coordination.",
+        "service_name" : "ZOOKEEPER",
+        "service_version" : "3.4.5.2.1",
+        "stack_name" : "HDP",
+        "stack_version" : "2.1"
+      },
+      "serviceComponents" : [
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/ZOOKEEPER/serviceComponents/ZOOKEEPER_CLIENT",
+          "StackServiceComponents" : {
+            "component_category" : "CLIENT",
+            "component_name" : "ZOOKEEPER_CLIENT",
+            "is_client" : true,
+            "is_master" : false,
+            "service_name" : "ZOOKEEPER",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        },
+        {
+          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/ZOOKEEPER/serviceComponents/ZOOKEEPER_SERVER",
+          "StackServiceComponents" : {
+            "component_category" : "MASTER",
+            "component_name" : "ZOOKEEPER_SERVER",
+            "is_client" : false,
+            "is_master" : true,
+            "service_name" : "ZOOKEEPER",
+            "stack_name" : "HDP",
+            "stack_version" : "2.1"
+          }
+        }
+      ]
+    }
+  ]
+}

+ 87 - 58
ambari-web/app/controllers/global/cluster_controller.js

@@ -19,9 +19,9 @@
 var App = require('app');
 
 App.ClusterController = Em.Controller.extend({
-  name:'clusterController',
-  cluster:null,
-  isLoaded:false,
+  name: 'clusterController',
+  cluster: null,
+  isLoaded: false,
   ambariProperties: null,
   ambariVersion: null,
   ambariViews: [],
@@ -30,7 +30,7 @@ App.ClusterController = Em.Controller.extend({
    * Whether we need to update statuses automatically or not
    */
   isWorking: false,
-  updateLoadStatus:function (item) {
+  updateLoadStatus: function (item) {
     var loadList = this.get('dataLoadList');
     var loaded = true;
     var numLoaded = 0;
@@ -39,12 +39,12 @@ App.ClusterController = Em.Controller.extend({
     for (var i in loadList) {
       if (loadList.hasOwnProperty(i)) {
         loadListLength++;
-        if(!loadList[i] && loaded){
+        if (!loadList[i] && loaded) {
           loaded = false;
         }
       }
       // calculate the number of true
-      if (loadList.hasOwnProperty(i) && loadList[i]){
+      if (loadList.hasOwnProperty(i) && loadList[i]) {
         numLoaded++;
       }
     }
@@ -55,6 +55,7 @@ App.ClusterController = Em.Controller.extend({
   dataLoadList:Em.Object.create({
     'hosts':false,
     'serviceMetrics':false,
+    'stackComponents':false,
     'services': false,
     'cluster':false,
     'clusterStatus':false,
@@ -66,7 +67,7 @@ App.ClusterController = Em.Controller.extend({
   /**
    * load cluster name
    */
-  loadClusterName:function (reload) {
+  loadClusterName: function (reload) {
     if (this.get('clusterName') && !reload) {
       return;
     }
@@ -78,7 +79,7 @@ App.ClusterController = Em.Controller.extend({
       error: 'loadClusterNameErrorCallback'
     });
 
-    if(!App.get('currentStackVersion')){
+    if (!App.get('currentStackVersion')) {
       App.set('currentStackVersion', App.defaultStackVersion);
     }
   },
@@ -105,7 +106,7 @@ App.ClusterController = Em.Controller.extend({
     return dfd.promise();
   },
 
-  getServerClock: function(){
+  getServerClock: function () {
     return App.ajax.send({
       name: 'ambari.service.load_server_clock',
       sender: this,
@@ -116,7 +117,7 @@ App.ClusterController = Em.Controller.extend({
   getServerClockSuccessCallback: function (data) {
     var clientClock = new Date().getTime();
     var serverClock = (data.RootServiceComponents.server_clock).toString();
-    serverClock = serverClock.length < 13? serverClock+ '000': serverClock;
+    serverClock = serverClock.length < 13 ? serverClock + '000' : serverClock;
     App.set('clockDistance', serverClock - clientClock);
     App.set('currentServerTime', parseInt(serverClock));
     console.log('loading ambari server clock distance');
@@ -125,7 +126,7 @@ App.ClusterController = Em.Controller.extend({
     console.log('Cannot load ambari server clock');
   },
 
-  getUrl:function (testUrl, url) {
+  getUrl: function (testUrl, url) {
     return (App.testMode) ? testUrl : App.apiPrefix + '/clusters/' + this.get('clusterName') + url;
   },
 
@@ -160,7 +161,7 @@ App.ClusterController = Em.Controller.extend({
       }
       return null;
     }
-  }.property('App.router.updateController.isUpdated', 'dataLoadList.hosts','gangliaWebProtocol'),
+  }.property('App.router.updateController.isUpdated', 'dataLoadList.hosts', 'gangliaWebProtocol'),
 
   /**
    * Provides the URL to use for NAGIOS server. This URL
@@ -169,7 +170,7 @@ App.ClusterController = Em.Controller.extend({
    *
    * If null is returned, it means NAGIOS service is not installed.
    */
-  nagiosUrl:function () {
+  nagiosUrl: function () {
     if (App.testMode) {
       return 'http://nagiosserver/nagios';
     } else {
@@ -194,7 +195,7 @@ App.ClusterController = Em.Controller.extend({
       }
       return null;
     }
-  }.property('App.router.updateController.isUpdated', 'dataLoadList.serviceMetrics', 'dataLoadList.hosts','nagiosWebProtocol'),
+  }.property('App.router.updateController.isUpdated', 'dataLoadList.serviceMetrics', 'dataLoadList.hosts', 'nagiosWebProtocol'),
 
   nagiosWebProtocol: function () {
     var properties = this.get('ambariProperties');
@@ -214,11 +215,11 @@ App.ClusterController = Em.Controller.extend({
     }
   }.property('ambariProperties'),
 
-  isNagiosInstalled:function () {
+  isNagiosInstalled: function () {
     return !!App.Service.find().findProperty('serviceName', 'NAGIOS');
   }.property('App.router.updateController.isUpdated', 'dataLoadList.serviceMetrics'),
 
-  isGangliaInstalled:function () {
+  isGangliaInstalled: function () {
     return !!App.Service.find().findProperty('serviceName', 'GANGLIA');
   }.property('App.router.updateController.isUpdated', 'dataLoadList.serviceMetrics'),
 
@@ -257,8 +258,8 @@ App.ClusterController = Em.Controller.extend({
    * Run <code>loadUpdatedStatus</code> with delay
    * @param delay
    */
-  loadUpdatedStatusDelayed: function(delay){
-    setTimeout(function(){
+  loadUpdatedStatusDelayed: function (delay) {
+    setTimeout(function () {
       App.updater.immediateRun('loadUpdatedStatus');
     }, delay);
   },
@@ -266,8 +267,8 @@ App.ClusterController = Em.Controller.extend({
   /**
    * Start polling, when <code>isWorking</code> become true
    */
-  startPolling: function(){
-    if(!this.get('isWorking')){
+  startPolling: function () {
+    if (!this.get('isWorking')) {
       return false;
     }
     App.updater.run(this, 'loadUpdatedStatus', 'isWorking', App.componentsUpdateInterval); //update will not run it immediately
@@ -277,7 +278,7 @@ App.ClusterController = Em.Controller.extend({
    *
    *  load all data and update load status
    */
-  loadClusterData:function () {
+  loadClusterData: function () {
     var self = this;
     this.loadAmbariProperties();
     this.loadAmbariViews();
@@ -285,7 +286,7 @@ App.ClusterController = Em.Controller.extend({
       return;
     }
 
-    if(this.get('isLoaded')) { // do not load data repeatedly
+    if (this.get('isLoaded')) { // do not load data repeatedly
       App.router.get('mainController').startPolling();
       return;
     }
@@ -294,7 +295,7 @@ App.ClusterController = Em.Controller.extend({
     var racksUrl = "/data/racks/racks.json";
 
     App.HttpClient.get(racksUrl, App.racksMapper, {
-      complete:function (jqXHR, textStatus) {
+      complete: function (jqXHR, textStatus) {
         self.updateLoadStatus('racks');
       }
     }, function (jqXHR, textStatus) {
@@ -302,53 +303,60 @@ App.ClusterController = Em.Controller.extend({
     });
 
     App.HttpClient.get(clusterUrl, App.clusterMapper, {
-      complete:function (jqXHR, textStatus) {
+      complete: function (jqXHR, textStatus) {
         self.updateLoadStatus('cluster');
       }
     }, function (jqXHR, textStatus) {
-        self.updateLoadStatus('cluster');
+      self.updateLoadStatus('cluster');
     });
 
     if (App.testMode) {
       self.updateLoadStatus('clusterStatus');
     } else {
-      App.clusterStatus.updateFromServer(true).complete(function() {
+      App.clusterStatus.updateFromServer(true).complete(function () {
         self.updateLoadStatus('clusterStatus');
       });
     }
-    
+
     App.HttpClient.get(usersUrl, App.usersMapper, {
-      complete:function (jqXHR, textStatus) {
+      complete: function (jqXHR, textStatus) {
         self.updateLoadStatus('users');
       }
     }, function (jqXHR, textStatus) {
-        self.updateLoadStatus('users');
+      self.updateLoadStatus('users');
     });
 
     /**
      * Order of loading:
-     * 1. request for services
-     * 2. put services in cache
-     * 3. request for hosts and host-components (single call)
-     * 4. request for service metrics
-     * 5. load host-components to model
-     * 6. load hosts to model
-     * 7. load services from cache with metrics to model
-     * 8. update stale_configs of host-components (depends on App.supports.hostOverrides)
+     * 1. request for service components supported by stack
+     * 2. load stack components to model
+     * 3. request for services
+     * 4. put services in cache
+     * 5. request for hosts and host-components (single call)
+     * 6. request for service metrics
+     * 7. load host-components to model
+     * 8. load hosts to model
+     * 9. load services from cache with metrics to model
+     * 10. update stale_configs of host-components (depends on App.supports.hostOverrides)
      */
-    App.router.get('updateController').updateServices(function () {
-      self.updateLoadStatus('services');
-      self.loadUpdatedStatus(function () {
-        self.updateLoadStatus('hosts');
-        if (App.supports.hostOverrides) {
-          App.router.get('updateController').updateComponentConfig(function () {
+    this.loadStackServiceComponents(function (data) {
+      require('utils/component').loadStackServiceComponentModel(data);
+      self.updateLoadStatus('stackComponents');
+      App.router.get('updateController').updateServices(function () {
+        self.updateLoadStatus('services');
+        self.loadUpdatedStatus(function () {
+          self.updateLoadStatus('hosts');
+          if (App.supports.hostOverrides) {
+            App.router.get('updateController').updateComponentConfig(function () {
+              self.updateLoadStatus('componentConfigs');
+            });
+          } else {
             self.updateLoadStatus('componentConfigs');
-          });
-        } else {
-          self.updateLoadStatus('componentConfigs');
-        }
-      }, true);
-      App.router.get('updateController').updateServiceMetric(function () {}, true);
+          }
+        }, true);
+        App.router.get('updateController').updateServiceMetric(function () {
+        }, true);
+      });
     });
   },
   /**
@@ -376,8 +384,8 @@ App.ClusterController = Em.Controller.extend({
     }
   },
 
-  requestHosts: function(realUrl, callback){
-    var testHostUrl =  App.get('isHadoop2Stack') ? '/data/hosts/HDP2/hosts.json':'/data/hosts/hosts.json';
+  requestHosts: function (realUrl, callback) {
+    var testHostUrl = App.get('isHadoop2Stack') ? '/data/hosts/HDP2/hosts.json' : '/data/hosts/hosts.json';
     var url = this.getUrl(testHostUrl, realUrl);
     App.HttpClient.get(url, App.hostsMapper, {
       complete: callback
@@ -418,7 +426,27 @@ App.ClusterController = Em.Controller.extend({
     }, this);
   },
 
-  loadAmbariProperties: function() {
+  /**
+   *
+   * @param callback
+   */
+  loadStackServiceComponents: function(callback) {
+    var callbackObj = {
+      loadStackServiceComponentsSuccess: callback
+    };
+    App.ajax.send({
+      name: 'wizard.service_components',
+      data: {
+        stackUrl: App.get('stack2VersionURL'),
+        stackVersion: App.get('currentStackVersionNumber'),
+        async: true
+      },
+      sender: callbackObj,
+      success: 'loadStackServiceComponentsSuccess'
+    });
+  },
+
+  loadAmbariProperties: function () {
     App.ajax.send({
       name: 'ambari.service',
       sender: this,
@@ -428,25 +456,26 @@ App.ClusterController = Em.Controller.extend({
     return this.get('ambariProperties');
   },
 
-  loadAmbariPropertiesSuccess: function(data) {
+  loadAmbariPropertiesSuccess: function (data) {
     console.log('loading ambari properties');
     this.set('ambariProperties', data.RootServiceComponents.properties);
     this.set('ambariVersion', data.RootServiceComponents.component_version);
   },
 
-  loadAmbariPropertiesError: function() {
+  loadAmbariPropertiesError: function () {
     console.warn('can\'t get ambari properties');
   },
 
-  clusterName:function () {
+  clusterName: function () {
     return (this.get('cluster')) ? this.get('cluster').Clusters.cluster_name : null;
   }.property('cluster'),
-  
+
   updateClusterData: function () {
-    var testUrl = App.get('isHadoop2Stack') ? '/data/clusters/HDP2/cluster.json':'/data/clusters/cluster.json';
+    var testUrl = App.get('isHadoop2Stack') ? '/data/clusters/HDP2/cluster.json' : '/data/clusters/cluster.json';
     var clusterUrl = this.getUrl(testUrl, '?fields=Clusters');
     App.HttpClient.get(clusterUrl, App.clusterMapper, {
-      complete:function(){}
+      complete: function () {
+      }
     });
   }
 });

+ 17 - 4
ambari-web/app/controllers/installer.js

@@ -181,6 +181,18 @@ App.InstallerController = App.WizardController.extend({
     return hosts;
   }.property('content.hosts'),
 
+  /**
+   * Load service components.
+   */
+  loadServiceComponentsDb: function () {
+    var serviceComponents = this.getDBProperty('serviceComponents');
+    if(serviceComponents && serviceComponents.items && serviceComponents.items.length) {
+      App.stackServiceComponentMapper.map(serviceComponents);
+    } else {
+      console.log("Failed to load Service components");
+    }
+  },
+
   stacks: [],
 
   /**
@@ -429,14 +441,14 @@ App.InstallerController = App.WizardController.extend({
    */
   saveClients: function (stepController) {
     var clients = [];
-    var serviceComponents = require('data/service_components');
+    var serviceComponents = App.StackServiceComponent.find();
 
     stepController.get('content').filterProperty('isSelected', true).forEach(function (_service) {
-      var client = serviceComponents.filterProperty('service_name', _service.serviceName).findProperty('isClient', true);
+      var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient', true);
       if (client) {
         clients.pushObject({
-          component_name: client.component_name,
-          display_name: client.display_name,
+          component_name: client.get('componentName'),
+          display_name: client.get('displayName'),
           isInstalled: false
         });
       }
@@ -561,6 +573,7 @@ App.InstallerController = App.WizardController.extend({
         this.loadConfirmedHosts();
       case '4':
         this.loadServices();
+        this.loadServiceComponentsDb();
       case '3':
         this.loadConfirmedHosts();
       case '2':

+ 9 - 11
ambari-web/app/controllers/main/host/add_controller.js

@@ -57,8 +57,6 @@ App.AddHostController = App.WizardController.extend({
     configGroups: null
   }),
 
-  components:require('data/service_components'),
-
   setCurrentStep: function (currentStep, completed) {
     this._super(currentStep, completed);
     App.clusterStatus.setClusterStatus({
@@ -175,14 +173,14 @@ App.AddHostController = App.WizardController.extend({
     });
 
     headers.forEach(function(header) {
-      var component = self.get('components').findProperty('component_name', header.get('name'));
+      var component = App.StackServiceComponent.find().findProperty('componentName', header.get('name'));
       hosts.forEach(function(host) {
         if (host.get('checkboxes').findProperty('title', component.display_name).checked) {
           masterComponentHosts .push({
-            display_name: component.display_name,
-            component: component.component_name,
+            display_name: component.get('displayName'),
+            component: component.get('componentName'),
             hostName: host.get('hostName'),
-            serviceId: component.service_name,
+            serviceId: component.get('serviceName'),
             isInstalled: false
           });
         }
@@ -230,16 +228,16 @@ App.AddHostController = App.WizardController.extend({
    */
   saveClients: function () {
     var clients = [];
-    var serviceComponents = require('data/service_components');
+    var serviceComponents = App.StackServiceComponent.find();
     var hostComponents = App.HostComponent.find();
 
     this.get('content.services').filterProperty('isSelected', true).forEach(function (_service) {
-      var client = serviceComponents.filterProperty('service_name', _service.serviceName).findProperty('isClient', true);
+      var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient', true);
       if (client) {
         clients.pushObject({
-          component_name: client.component_name,
-          display_name: client.display_name,
-          isInstalled: hostComponents.filterProperty('componentName', client.component_name).length > 0
+          component_name: client.get('componentName'),
+          display_name: client.get('displayName'),
+          isInstalled: hostComponents.filterProperty('componentName', client.get('componentName')).length > 0
         });
       }
     }, this);

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

@@ -275,16 +275,16 @@ App.AddServiceController = App.WizardController.extend({
    */
   saveClients: function(stepController){
     var clients = [];
-    var serviceComponents = require('data/service_components');
+    var serviceComponents = App.StackServiceComponent.find();
     var hostComponents = App.HostComponent.find();
 
     stepController.get('content').filterProperty('isSelected',true).forEach(function (_service) {
-      var client = serviceComponents.filterProperty('service_name', _service.serviceName).findProperty('isClient', true);
+      var client = serviceComponents.filterProperty('serviceName', _service.serviceName).findProperty('isClient', true);
       if (client) {
         clients.pushObject({
-          component_name: client.component_name,
-          display_name: client.display_name,
-          isInstalled: hostComponents.filterProperty('componentName', client.component_name).length > 0
+          component_name: client.get('componentName'),
+          display_name: client.get('displayName'),
+          isInstalled: hostComponents.filterProperty('componentName', client.get('componentName')).length > 0
         });
       }
     }, this);

+ 0 - 1
ambari-web/app/controllers/main/service/item.js

@@ -17,7 +17,6 @@
  */
 
 var App = require('app');
-var service_components = require('data/service_components');
 var batchUtils = require('utils/batch_scheduled_requests');
 
 App.MainServiceItemController = Em.Controller.extend({

+ 1 - 2
ambari-web/app/controllers/main/service/manage_config_groups_controller.js

@@ -20,7 +20,6 @@
 var App = require('app');
 var hostsManagement = require('utils/hosts');
 var componentHelper = require('utils/component');
-var serviceComponents = require('data/service_components');
 
 App.ManageConfigGroupsController = Em.Controller.extend({
   name: 'manageConfigGroupsController',
@@ -252,7 +251,7 @@ App.ManageConfigGroupsController = Em.Controller.extend({
    * @return {Array}
    */
   componentsForFilter: function () {
-    return serviceComponents.filterProperty('service_name', this.get('serviceName')).map(function (component) {
+    return App.StackServiceComponent.find().filterProperty('serviceName', this.get('serviceName')).map(function (component) {
       return Em.Object.create({
         displayName: component.display_name,
         componentName: component.isClient ? 'CLIENT' : component.component_name,

+ 26 - 12
ambari-web/app/controllers/wizard.js

@@ -40,10 +40,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
   },
 
   slaveComponents: function () {
-    return require('data/service_components').filter(function (component) {
-      return !(component.isClient || component.isMaster ||
-        ["GANGLIA_MONITOR", "DASHBOARD", "MYSQL_SERVER"].contains(component.component_name));
-    });
+    return App.StackServiceComponent.find().filterProperty('isSlave',true);
   }.property(),
 
   allHosts: App.Host.find(),
@@ -414,6 +411,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
     this.setDBProperty('allHostNames', undefined);
     this.setDBProperty('installOptions', undefined);
     this.setDBProperty('allHostNamesPattern', undefined);
+    this.setDBProperty('serviceComponents', undefined);
   },
 
   installOptionsTemplate: {
@@ -439,7 +437,8 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
       sender: this,
       data: {
         stackUrl: App.get('stack2VersionURL'),
-        stackVersion: App.get('currentStackVersionNumber')
+        stackVersion: App.get('currentStackVersionNumber'),
+        async: false
       },
       success: 'loadServiceComponentsSuccessCallback',
       error: 'loadServiceComponentsErrorCallback'
@@ -448,10 +447,24 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
   },
 
   loadServiceComponentsSuccessCallback: function (jsonData) {
-    var displayOrderConfig = require('data/services');
+    this.setServices(jsonData);
+    this.setServiceComponents(jsonData);
     console.log("TRACE: getService ajax call  -> In success function for the getServiceComponents call");
     console.log("TRACE: jsonData.services : " + jsonData.items);
+  },
+
+  loadServiceComponentsErrorCallback: function (request, ajaxOptions, error) {
+    console.log("TRACE: STep5 -> In error function for the getServiceComponents call");
+    console.log("TRACE: STep5 -> error code status is: " + request.status);
+    console.log('Step8: Error message is: ' + request.responseText);
+  },
 
+  /**
+   *
+   * @param jsonData
+   */
+  setServices: function(jsonData) {
+    var displayOrderConfig = require('data/services');
     // Creating Model
     var Service = Ember.Object.extend({
       serviceName: null,
@@ -488,14 +501,15 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, {
     }
 
     this.set('loadedServiceComponents', data);
-    console.log('TRACE: service components: ' + JSON.stringify(data));
-
   },
 
-  loadServiceComponentsErrorCallback: function (request, ajaxOptions, error) {
-    console.log("TRACE: STep5 -> In error function for the getServiceComponents call");
-    console.log("TRACE: STep5 -> error code status is: " + request.status);
-    console.log('Step8: Error message is: ' + request.responseText);
+  /**
+   *
+   * @param jsonData
+   */
+  setServiceComponents: function(jsonData) {
+    var serviceComponents = require('utils/component').loadStackServiceComponentModel(jsonData);
+    this.setDBProperty('serviceComponents', serviceComponents);
   },
 
   loadServicesFromServer: function () {

+ 28 - 34
ambari-web/app/controllers/wizard/step5_controller.js

@@ -70,8 +70,6 @@ App.WizardStep5Controller = Em.Controller.extend({
   servicesMasters:[],
   selectedServicesMasters:[],
 
-  components:require('data/service_components'),
-
   clearStep:function () {
     this.set('hosts', []);
     this.set('selectedServicesMasters', []);
@@ -162,55 +160,52 @@ App.WizardStep5Controller = Em.Controller.extend({
     var services = this.get('content.services')
       .filterProperty('isSelected', true).mapProperty('serviceName'); //list of shown services
 
-    var masterComponents = this.get('components').filterProperty('isMaster', true); //get full list from mock data
+    var masterComponents = App.StackServiceComponent.find().filterProperty('isShownOnInstallerAssignMasterPage', true); //get full list from mock data
     var masterHosts = this.get('content.masterComponentHosts'); //saved to local storage info
 
     var resultComponents = [];
 
     var servicesLength = services.length;
     for (var index = 0; index < servicesLength; index++) {
-      var componentInfo = masterComponents.filterProperty('service_name', services[index]);
+      var componentInfo = masterComponents.filterProperty('serviceName', services[index]);
 
       componentInfo.forEach(function (_componentInfo) {
-        if (_componentInfo.component_name == 'ZOOKEEPER_SERVER' || _componentInfo.component_name == 'HBASE_MASTER') {
-          var savedComponents = masterHosts.filterProperty('component', _componentInfo.component_name);
+        if (_componentInfo.get('componentName') == 'ZOOKEEPER_SERVER' || _componentInfo.get('componentName') == 'HBASE_MASTER') {
+          var savedComponents = masterHosts.filterProperty('component', _componentInfo.get('componentName'));
           if (savedComponents.length) {
-
             savedComponents.forEach(function (item) {
-              var zooKeeperHost = {};
-              zooKeeperHost.display_name = _componentInfo.display_name;
-              zooKeeperHost.component_name = _componentInfo.component_name;
-              zooKeeperHost.selectedHost = item.hostName;
-              zooKeeperHost.serviceId = services[index];
-              zooKeeperHost.isInstalled = item.isInstalled;
-              zooKeeperHost.isHiveCoHost = false;
-              resultComponents.push(zooKeeperHost);
+              var multipleMasterHost = {};
+              multipleMasterHost.display_name = _componentInfo.get('displayName');
+              multipleMasterHost.component_name = _componentInfo.get('componentName');
+              multipleMasterHost.selectedHost = item.hostName;
+              multipleMasterHost.serviceId = services[index];
+              multipleMasterHost.isInstalled = item.isInstalled;
+              multipleMasterHost.isHiveCoHost = false;
+              resultComponents.push(multipleMasterHost);
             })
-
           } else {
-
-            var zooHosts = this.selectHost(_componentInfo.component_name);
+            var zooHosts = this.selectHost(_componentInfo.get('componentName'));
             zooHosts.forEach(function (_host) {
-              var zooKeeperHost = {};
-              zooKeeperHost.display_name = _componentInfo.display_name;
-              zooKeeperHost.component_name = _componentInfo.component_name;
-              zooKeeperHost.selectedHost = _host;
-              zooKeeperHost.serviceId = services[index];
-              zooKeeperHost.isInstalled = false;
-              zooKeeperHost.isHiveCoHost = false;
-              resultComponents.push(zooKeeperHost);
+              var multipleMasterHost = {};
+              multipleMasterHost.display_name = _componentInfo.get('displayName');
+              multipleMasterHost.component_name = _componentInfo.get('componentName');
+              multipleMasterHost.selectedHost = _host;
+              multipleMasterHost.serviceId = services[index];
+              multipleMasterHost.isInstalled = false;
+              multipleMasterHost.isHiveCoHost = false;
+              resultComponents.push(multipleMasterHost);
             });
 
           }
         } else {
-          var savedComponent = masterHosts.findProperty('component', _componentInfo.component_name);
+          var savedComponent = masterHosts.findProperty('component', _componentInfo.get('componentName'));
           var componentObj = {};
-          componentObj.component_name = _componentInfo.component_name;
-          componentObj.display_name = _componentInfo.display_name;
-          componentObj.selectedHost = savedComponent ? savedComponent.hostName : this.selectHost(_componentInfo.component_name);   // call the method that plays selectNode algorithm or fetches from server
+          componentObj.component_name = _componentInfo.get('componentName');
+          componentObj.display_name = _componentInfo.get('displayName');
+          componentObj.selectedHost = savedComponent ? savedComponent.hostName : this.selectHost(_componentInfo.get('componentName'));   // call the method that plays selectNode algorithm or fetches from server
           componentObj.isInstalled = savedComponent ? savedComponent.isInstalled : false;
           componentObj.serviceId = services[index];
-          componentObj.isHiveCoHost = ['HIVE_METASTORE', 'WEBHCAT_SERVER'].contains(_componentInfo.component_name) && !this.get('isReassignWizard');
+          componentObj.isHiveCoHost = ['HIVE_METASTORE', 'WEBHCAT_SERVER'].contains(_componentInfo.get('componentName')) && !this.get('isReassignWizard');
           resultComponents.push(componentObj);
         }
       }, this);
@@ -227,7 +222,7 @@ App.WizardStep5Controller = Em.Controller.extend({
     var self = this;
     var services = this.get('content.services')
       .filterProperty('isInstalled', true).mapProperty('serviceName'); //list of shown services
-    var showRemoveControlZk = !services.contains('ZOOKEEPER') && masterComponents.filterProperty('display_name', 'ZooKeeper').length > 1;
+    var showRemoveControlZk = !services.contains('ZOOKEEPER') && masterComponents.filterProperty('component_name', 'ZOOKEEPER_SERVER').length > 1;
     var showRemoveControlHb = !services.contains('HBASE') && masterComponents.filterProperty('component_name', 'HBASE_MASTER').length > 1;
     var zid = 1;
     var hid = 1;
@@ -247,7 +242,7 @@ App.WizardStep5Controller = Em.Controller.extend({
       var componentObj = Ember.Object.create(item);
       console.log("TRACE: render master component name is: " + item.component_name);
 
-      if (item.display_name === "ZooKeeper") {
+      if (item.component_name === "ZOOKEEPER_SERVER") {
         componentObj.set('zId', zid++);
         componentObj.set("showRemoveControl", showRemoveControlZk);
       } else if (App.supports.multipleHBaseMasters && item.component_name === "HBASE_MASTER") {
@@ -454,7 +449,6 @@ App.WizardStep5Controller = Em.Controller.extend({
     var mapping = [], mappingObject, mappedHosts, hostObj;
     //get the unique assigned hosts and find the master services assigned to them
     mappedHosts = this.get("selectedServicesMasters").mapProperty("selectedHost").uniq();
-
     mappedHosts.forEach(function (item) {
       hostObj = this.get("hosts").findProperty("host_name", item);
 

+ 2 - 3
ambari-web/app/controllers/wizard/step6_controller.js

@@ -53,7 +53,6 @@ App.WizardStep6Controller = Em.Controller.extend({
   isMasters: false,
   isLoaded: false,
 
-  components: require('data/service_components'),
 
   isAddHostWizard: function () {
     return this.get('content.controllerName') === 'addHostController';
@@ -187,7 +186,7 @@ App.WizardStep6Controller = Em.Controller.extend({
   },
 
   getComponentDisplayName: function (componentName) {
-    return this.get('components').findProperty('component_name', componentName).display_name
+    return App.StackServiceComponent.find().findProperty('componentName', componentName).get('displayName')
   },
 
   loadStep: function () {
@@ -252,7 +251,7 @@ App.WizardStep6Controller = Em.Controller.extend({
       }
       headers.pushObject(Ember.Object.create({
         name: 'CLIENT',
-        label: self.getComponentDisplayName('CLIENT')
+        label: App.format.role('CLIENT')
       }));
     }
 

+ 3 - 3
ambari-web/app/controllers/wizard/step7_controller.js

@@ -632,7 +632,7 @@ App.WizardStep7Controller = Em.Controller.extend({
     var selectedServiceName = this.get('selectedService.serviceName');
     var masterComponents = this.get('content.masterComponentHosts');
     var slaveComponents = this.get('content.slaveComponentHosts');
-    var scMaps = require('data/service_components');
+    var scMaps = App.StackServiceComponent.find();
     
     var validComponents = Ember.A([]);
     var seenComponents = {};
@@ -651,8 +651,8 @@ App.WizardStep7Controller = Em.Controller.extend({
     slaveComponents.forEach(function(component){
       var cn = component.componentName;
       var cdn = component.displayName;
-      var componentDef = scMaps.findProperty('component_name', cn);
-      if(componentDef!=null && selectedServiceName===componentDef.service_name && !seenComponents[cn]){
+      var componentDef = scMaps.findProperty('componentName', cn);
+      if(!!componentDef && selectedServiceName===componentDef.get('serviceName') && !seenComponents[cn]){
         validComponents.pushObject(Ember.Object.create({
           componentName: cn,
           displayName: cdn,

+ 3 - 4
ambari-web/app/controllers/wizard/step8_controller.js

@@ -954,11 +954,11 @@ App.WizardStep8Controller = Em.Controller.extend({
    * One request for each service!
    */
   createComponents: function () {
-    var serviceComponents = require('data/service_components');
+    var serviceComponents = App.StackServiceComponent.find();
     this.get('selectedServices').forEach(function (_service) {
       var serviceName = _service.get('serviceName');
-      var componentsData = serviceComponents.filterProperty('service_name', serviceName).map(function (_component) {
-        return { "ServiceComponentInfo": { "component_name": _component.component_name } };
+      var componentsData = serviceComponents.filterProperty('serviceName', serviceName).map(function (_component) {
+        return { "ServiceComponentInfo": { "component_name": _component.get('componentName') } };
       });
 
       // Service must be specified in terms of a query for creating multiple components at the same time.
@@ -969,7 +969,6 @@ App.WizardStep8Controller = Em.Controller.extend({
         data: JSON.stringify({"components": componentsData})
       });
     }, this);
-
   },
 
   /**

+ 2 - 3
ambari-web/app/controllers/wizard/step9_controller.js

@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 var App = require('app');
-var serviceComponents = require('data/service_components');
 
 App.WizardStep9Controller = Em.Controller.extend({
   name: 'wizardStep9Controller',
@@ -476,8 +475,8 @@ App.WizardStep9Controller = Em.Controller.extend({
       var OnlyClients = true;
       var tasks = host.get('logTasks');
       tasks.forEach(function (task) {
-        var component = serviceComponents.findProperty('component_name', task.Tasks.role);
-        if (!(component && component.isClient)) {
+        var component = App.StackServiceComponent.find().findProperty('componentName', task.Tasks.role);
+        if (!(component && component.get('isClient'))) {
           OnlyClients = false;
         }
       });

+ 86 - 120
ambari-web/app/data/HDP2/global_properties.js

@@ -79,7 +79,7 @@ require('config');
 module.exports =
 {
   "configProperties": [
-    /**********************************************HDFS***************************************/
+  /**********************************************HDFS***************************************/
     {
       "id": "puppet var",
       "name": "namenode_host",
@@ -397,35 +397,34 @@ module.exports =
       "serviceName": "YARN",
       "category": "Advanced"
     },
-// @todo uncomment after App Timeline service integration
-//    {
-//      "id": "puppet var",
-//      "name": "ats_host",
-//      "displayName": "App Timeline Server",
-//      "description": "Application Timeline Server Host",
-//      "defaultValue": "",
-//      "isOverridable": false,
-//      "displayType": "masterHost",
-//      "isRequiredByAgent": false,
-//      "isVisible": true,
-//      "serviceName": "YARN",
-//      "category": "AppTimelineServer",
-//      "index": 0
-//    },
-//    {
-//      "id": "puppet var",
-//      "name": "apptimelineserver_heapsize",
-//      "displayName": "AppTimelineServer Java heap size",
-//      "description": "AppTimelineServer Java heap size",
-//      "defaultValue": "1024",
-//      "isOverridable": false,
-//      "displayType": "int",
-//      "unit": "MB",
-//      "isVisible": true,
-//      "serviceName": "YARN",
-//      "category": "AppTimelineServer",
-//      "index": 1
-//    }
+    {
+      "id": "puppet var",
+      "name": "ats_host",
+      "displayName": "App Timeline Server",
+      "description": "Application Timeline Server Host",
+      "defaultValue": "",
+      "isOverridable": false,
+      "displayType": "masterHost",
+      "isRequiredByAgent": false,
+      "isVisible": true,
+      "serviceName": "YARN",
+      "category": "AppTimelineServer",
+      "index": 0
+    },
+    {
+      "id": "puppet var",
+      "name": "apptimelineserver_heapsize",
+      "displayName": "AppTimelineServer Java heap size",
+      "description": "AppTimelineServer Java heap size",
+      "defaultValue": "1024",
+      "isOverridable": false,
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "serviceName": "YARN",
+      "category": "AppTimelineServer",
+      "index": 1
+    },
   /**********************************************HBASE***************************************/
     {
       "id": "puppet var",
@@ -513,7 +512,7 @@ module.exports =
       "serviceName": "HBASE",
       "category": "Advanced"
     },
-    /**********************************************GLUSTERFS***************************************/
+  /**********************************************GLUSTERFS***************************************/
     {
       "id": "puppet var",
       "name": "glusterfs_defaultFS_name",
@@ -527,30 +526,30 @@ module.exports =
       "category": "General"
     },
     {
-        "id": "puppet var",
-        "name": "fs_glusterfs_default_name",
-        "displayName": "GlusterFS default fs name",
-        "description": "GlusterFS default filesystem name (glusterfs:///)",
-        "defaultValue": "glusterfs:///",
-        "displayType": "string",
-        "isVisible": true,
-        "domain": "global",
-        "serviceName": "GLUSTERFS",
-        "category": "General"
-      },
-          {
-            "id": "puppet var",
-            "name": "hadoop_heapsize",
-            "displayName": "Hadoop maximum Java heap size",
-            "description": "Maximum Java heap size for daemons such as Balancer (Java option -Xmx)",
-            "defaultValue": "1024",
-            "displayType": "int",
-            "unit": "MB",
-            "isVisible": true,
-            "domain": "global",
-            "serviceName": "GLUSTERFS",
-            "category": "General"
-          },
+      "id": "puppet var",
+      "name": "fs_glusterfs_default_name",
+      "displayName": "GlusterFS default fs name",
+      "description": "GlusterFS default filesystem name (glusterfs:///)",
+      "defaultValue": "glusterfs:///",
+      "displayType": "string",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "GLUSTERFS",
+      "category": "General"
+    },
+    {
+      "id": "puppet var",
+      "name": "hadoop_heapsize",
+      "displayName": "Hadoop maximum Java heap size",
+      "description": "Maximum Java heap size for daemons such as Balancer (Java option -Xmx)",
+      "defaultValue": "1024",
+      "displayType": "int",
+      "unit": "MB",
+      "isVisible": true,
+      "domain": "global",
+      "serviceName": "GLUSTERFS",
+      "category": "General"
+    },
 
   /**********************************************HIVE***************************************/
     {
@@ -971,10 +970,10 @@ module.exports =
           foreignKeys: ['oozie_derby_database']
         },
         /*{
-          displayName: 'New MySQL Database',
-          foreignKeys: ['oozie_ambari_database', 'oozie_ambari_host'],
-          hidden: !App.supports.hiveOozieExtraDatabases
-        },*/
+         displayName: 'New MySQL Database',
+         foreignKeys: ['oozie_ambari_database', 'oozie_ambari_host'],
+         hidden: !App.supports.hiveOozieExtraDatabases
+         },*/
         {
           displayName: 'Existing MySQL Database',
           foreignKeys: ['oozie_existing_mysql_database', 'oozie_existing_mysql_host'],
@@ -1542,7 +1541,7 @@ module.exports =
       "isRequiredByAgent": false,
       "serviceName": "MISC",
       "category": "General",
-      "belongsToService":[]
+      "belongsToService": []
     },
     {
       "id": "puppet var",
@@ -1557,7 +1556,7 @@ module.exports =
       "filename": "core-site.xml",
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HIVE","WEBHCAT","OOZIE","FALCON"],
+      "belongsToService": ["HIVE", "WEBHCAT", "OOZIE", "FALCON"],
       "index": 18
     },
     {
@@ -1571,7 +1570,7 @@ module.exports =
       "isVisible": false,
       "serviceName": "MISC",
       "category": "General",
-      "belongsToService":[]
+      "belongsToService": []
     },
     {
       "id": "puppet var",
@@ -1585,7 +1584,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HDFS"],
+      "belongsToService": ["HDFS"],
       "index": 1
     },
     {
@@ -1600,7 +1599,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["MAPREDUCE2"],
+      "belongsToService": ["MAPREDUCE2"],
       "index": 2
     },
     {
@@ -1615,7 +1614,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["YARN"],
+      "belongsToService": ["YARN"],
       "index": 3
     },
     {
@@ -1630,7 +1629,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HBASE"],
+      "belongsToService": ["HBASE"],
       "index": 4
     },
     {
@@ -1645,7 +1644,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HIVE"],
+      "belongsToService": ["HIVE"],
       "index": 5
     },
     {
@@ -1660,7 +1659,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HCATALOG"],
+      "belongsToService": ["HCATALOG"],
       "index": 6
     },
     {
@@ -1675,7 +1674,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["WEBHCAT"],
+      "belongsToService": ["WEBHCAT"],
       "index": 7
     },
     {
@@ -1690,7 +1689,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["OOZIE"],
+      "belongsToService": ["OOZIE"],
       "index": 8
     },
     {
@@ -1703,9 +1702,9 @@ module.exports =
       "displayType": "user",
       "isOverridable": false,
       "isVisible": true,
-      "serviceName":"MISC",
+      "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["FALCON"],
+      "belongsToService": ["FALCON"],
       "index": 10
     },
     {
@@ -1718,9 +1717,9 @@ module.exports =
       "displayType": "user",
       "isOverridable": false,
       "isVisible": true,
-      "serviceName":"MISC",
+      "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["STORM"],
+      "belongsToService": ["STORM"],
       "index": 9
     },
     {
@@ -1735,7 +1734,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["ZOOKEEPER"],
+      "belongsToService": ["ZOOKEEPER"],
       "index": 11
     },
     {
@@ -1750,7 +1749,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["GANGLIA"],
+      "belongsToService": ["GANGLIA"],
       "index": 12
     },
     {
@@ -1763,9 +1762,9 @@ module.exports =
       "displayType": "advanced",
       "isOverridable": false,
       "isVisible": false,
-      "serviceName":"MISC",
+      "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":[]
+      "belongsToService": []
     },
     {
       "id": "puppet var",
@@ -1777,9 +1776,9 @@ module.exports =
       "displayType": "user",
       "isOverridable": false,
       "isVisible": true,
-      "serviceName":"MISC",
+      "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["NAGIOS"],
+      "belongsToService": ["NAGIOS"],
       "index": 14
     },
     {
@@ -1792,9 +1791,9 @@ module.exports =
       "displayType": "user",
       "isOverridable": false,
       "isVisible": true,
-      "serviceName":"MISC",
+      "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["NAGIOS"],
+      "belongsToService": ["NAGIOS"],
       "index": 13
     },
     {
@@ -1809,7 +1808,7 @@ module.exports =
       "isVisible": App.supports.customizeSmokeTestUser,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HDFS"],
+      "belongsToService": ["HDFS"],
       "index": 16
     },
     {
@@ -1822,9 +1821,9 @@ module.exports =
       "displayType": "user",
       "isOverridable": false,
       "isVisible": true,
-      "serviceName":"MISC",
+      "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["TEZ"],
+      "belongsToService": ["TEZ"],
       "index": 15
     },
     {
@@ -1839,7 +1838,7 @@ module.exports =
       "isVisible": true,
       "serviceName": "MISC",
       "category": "Users and Groups",
-      "belongsToService":["HDFS"],
+      "belongsToService": ["HDFS"],
       "index": 16
     },
     {
@@ -1854,41 +1853,8 @@ module.exports =
       "isVisible": true,
       "serviceName": "GANGLIA",
       "category": "General",
-      "belongsToService":["GANGLIA"]
+      "belongsToService": ["GANGLIA"]
     }
 
   ]
 };
-// @todo remove after App Timeline service integration
-if (App.supports.appTimelineServer) {
-  module.exports.configProperties.push(
-    {
-      "id": "puppet var",
-      "name": "ats_host",
-      "displayName": "App Timeline Server",
-      "description": "Application Timeline Server Host",
-      "defaultValue": "",
-      "isOverridable": false,
-      "displayType": "masterHost",
-      "isRequiredByAgent": false,
-      "isVisible": true,
-      "serviceName": "YARN",
-      "category": "AppTimelineServer",
-      "index": 0
-    },
-    {
-      "id": "puppet var",
-      "name": "apptimelineserver_heapsize",
-      "displayName": "AppTimelineServer Java heap size",
-      "description": "AppTimelineServer Java heap size",
-      "defaultValue": "1024",
-      "isOverridable": false,
-      "displayType": "int",
-      "unit": "MB",
-      "isVisible": true,
-      "serviceName": "YARN",
-      "category": "AppTimelineServer",
-      "index": 1
-    }
-  );
-}

+ 0 - 423
ambari-web/app/data/service_components.js

@@ -1,423 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var App = require('app');
-
-module.exports = new Ember.Set([
-
-  {
-    service_name: 'HDFS',
-    component_name: 'NAMENODE',
-    display_name: 'NameNode',
-    isMaster: true,
-    isClient: false,
-    description: 'Master server that manages the file system namespace and regulates access to files by clients'
-  },
-  {
-    service_name: 'HDFS',
-    component_name: 'SECONDARY_NAMENODE',
-    display_name: 'SNameNode',
-    isMaster: true,
-    isClient: false,
-    description: 'Helper to the primary NameNode that is responsible for supporting periodic checkpoints of the HDFS metadata'
-  },
-  {
-    service_name: 'HDFS',
-    component_name: 'DATANODE',
-    display_name: 'DataNode',
-    isMaster: false,
-    isClient: false,
-    description: 'The slave for HDFS'
-  },
-  {
-    service_name: 'HDFS',
-    component_name: 'HDFS_CLIENT',
-    display_name: 'HDFS Client',
-    isMaster: false,
-    isClient: true,
-    description: 'Client component for HDFS'
-  },
-  {
-    service_name: 'MAPREDUCE',
-    component_name: 'JOBTRACKER',
-    display_name: 'JobTracker',
-    isMaster: true,
-    isClient: false,
-    description: 'Central Master service that pushes work (MR tasks) out to available TaskTracker nodes in the cluster'
-  },
-  {
-    service_name: 'MAPREDUCE',
-    component_name: 'HISTORYSERVER',
-    display_name: 'History Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'MAPREDUCE',
-    component_name: 'TASKTRACKER',
-    display_name: 'TaskTracker',
-    isMaster: false,
-    isClient: false,
-    description: 'The slave for MapReduce'
-  },
-  {
-    service_name: 'MAPREDUCE',
-    component_name: 'MAPREDUCE_CLIENT',
-    display_name: 'MapReduce Client',
-    isMaster: false,
-    isClient: true,
-    description: 'Client component for MapReduce'
-  },
-  {
-    service_name: 'MAPREDUCE2',
-    component_name: 'MAPREDUCE2_CLIENT',
-    display_name: 'MapReduce 2 Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'MAPREDUCE2',
-    component_name: 'HISTORYSERVER',
-    display_name: 'History Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'TEZ',
-    component_name: 'TEZ_CLIENT',
-    display_name: 'Tez Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'YARN',
-    component_name: 'RESOURCEMANAGER',
-    display_name: 'ResourceManager',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'YARN',
-    component_name: 'YARN_CLIENT',
-    display_name: 'YARN Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  // @todo uncomment after Application Timeline Server API implementation
-//  {
-//    service_name: 'YARN',
-//    component_name: 'APP_TIMELINE_SERVER',
-//    display_name: 'App Timeline Server',
-//    isMaster: true,
-//    isClient: false,
-//    stackVersions: ['2.1.1'],
-//    description: ''
-//  },
-  {
-    service_name: 'YARN',
-    component_name: 'NODEMANAGER',
-    display_name: 'NodeManager',
-    isMaster: false,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'ZOOKEEPER',
-    component_name: 'ZOOKEEPER_SERVER',
-    display_name: 'ZooKeeper',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'ZOOKEEPER',
-    component_name: 'ZOOKEEPER_CLIENT',
-    display_name: 'ZooKeeper Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'HBASE',
-    component_name: 'HBASE_MASTER',
-    display_name: 'HBase Master',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'HBASE',
-    component_name: 'HBASE_REGIONSERVER',
-    display_name: 'RegionServer',
-    isMaster: false,
-    isClient: false,
-    description: 'The slave for HBase'
-  },
-  {
-    service_name: 'HBASE',
-    component_name: 'HBASE_CLIENT',
-    display_name: 'HBase Client',
-    isMaster: false,
-    isClient: true,
-    description: 'The slave for HBase'
-  },
-  {
-    service_name: 'PIG',
-    component_name: 'PIG',
-    display_name: 'Pig',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'SQOOP',
-    component_name: 'SQOOP',
-    display_name: 'Sqoop',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'OOZIE',
-    component_name: 'OOZIE_SERVER',
-    display_name: 'Oozie Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'OOZIE',
-    component_name: 'OOZIE_CLIENT',
-    display_name: 'Oozie Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'HIVE',
-    component_name: 'HIVE_SERVER',
-    display_name: 'HiveServer2',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'HIVE',
-    component_name: 'HIVE_METASTORE',
-    display_name: 'Hive Metastore',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'HIVE',
-    component_name: 'HIVE_CLIENT',
-    display_name: 'Hive Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'HIVE',
-    component_name: 'MYSQL_SERVER',
-    display_name: 'MySQL Server for Hive',
-    isMaster: false,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'HCATALOG',
-    component_name: 'HCAT',
-    display_name: 'HCat Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'WEBHCAT',
-    component_name: 'WEBHCAT_SERVER',
-    display_name: 'WebHCat Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'DASHBOARD',
-    component_name: 'DASHBOARD',
-    display_name: 'Monitoring Dashboard',
-    isMaster: false,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'NAGIOS',
-    component_name: 'NAGIOS_SERVER',
-    display_name: 'Nagios Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'GANGLIA',
-    component_name: 'GANGLIA_SERVER',
-    display_name: 'Ganglia Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'GANGLIA',
-    component_name: 'GANGLIA_MONITOR',
-    display_name: 'Ganglia Slave',
-    isMaster: false,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'KERBEROS',
-    component_name: 'KERBEROS_SERVER',
-    display_name: 'Kerberos Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  {
-    service_name: 'KERBEROS',
-    component_name: 'KERBEROS_ADMIN_CLIENT',
-    display_name: 'Kerberos Admin Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'KERBEROS',
-    component_name: 'KERBEROS_CLIENT',
-    display_name: 'Kerberos Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'CLIENT',
-    component_name: 'CLIENT',
-    display_name: 'Client',
-    isMaster: false,
-    isClient: true,
-    description: ''
-  },
-  {
-    service_name: 'HUE',
-    component_name: 'HUE_SERVER',
-    display_name: 'Hue Server',
-    isMaster: true,
-    isClient: false,
-    description: ''
-  },
-  { 
-    service_name: 'GLUSTERFS',
-    component_name: 'GLUSTERFS_CLIENT',
-    display_name: 'GLUSTERFS Client', 
-    isMaster: false, 
-    isClient: true, 
-    description: 'Client component for GLUSTERFS'
-  },
-  {
-    service_name: 'FALCON',
-    component_name: 'FALCON_SERVER',
-    display_name: 'Falcon Server',
-    isMaster: true,
-    isClient: false,
-    description: 'Falcon Server for mirroring'
-  },
-  {
-    service_name: 'FALCON',
-    component_name: 'FALCON_CLIENT',
-    display_name: 'Falcon Client',
-    isMaster: false,
-    isClient: true,
-    description: 'Falcon Client for mirroring'
-  },
-  {
-    service_name: 'STORM',
-    component_name: 'NIMBUS',
-    display_name: 'Nimbus',
-    isMaster: true,
-    isClient: false,
-    description: 'Master component for STORM'
-  },
-  {
-    service_name: 'STORM',
-    component_name: 'SUPERVISOR',
-    display_name: 'Supervisor',
-    isMaster: false,
-    isClient: false,
-    description: 'Slave component for STORM'
-  },
-  {
-    service_name: 'STORM',
-    component_name: 'STORM_UI_SERVER',
-    display_name: 'Storm UI Server',
-    isMaster: true,
-    isClient: false,
-    description: 'Master component for STORM'
-  },
-  {
-    service_name: 'STORM',
-    component_name: 'DRPC_SERVER',
-    display_name: 'DRPC Server',
-    isMaster: true,
-    isClient: false,
-    description: 'Master component for STORM'
-  },
-  {
-    service_name: 'STORM',
-    component_name: 'STORM_REST_API',
-    display_name: 'Storm REST API Server',
-    isMaster: true,
-    isClient: false,
-    description: 'Master component for STORM'
-  },
-  {
-    service_name: 'FLUME',
-    component_name: 'FLUME_HANDLER',
-    display_name: 'Flume Agent',
-    isMaster: false,
-    isClient: false,
-    description: 'Slave component for Flume'
-  }
-]);
-
-// @todo remove after Application Timeline Server API implementation
-if (App.supports.appTimelineServer) {
-  var appTimelineServerObj = {
-    service_name: 'YARN',
-    component_name: 'APP_TIMELINE_SERVER',
-    display_name: 'App Timeline Server',
-    isMaster: true,
-    isClient: false,
-    stackVersions: ['2.1'],
-    description: ''
-  };
-  module.exports.push(appTimelineServerObj);
-}

+ 2 - 14
ambari-web/app/initialize.js

@@ -36,20 +36,8 @@ require('router');
 require('utils/ajax');
 require('utils/updater');
 
-require('mappers/server_data_mapper');
-require('mappers/status_mapper');
-require('mappers/hosts_mapper');
-require('mappers/cluster_mapper');
-require('mappers/jobs_mapper');
-require('mappers/runs_mapper');
-require('mappers/racks_mapper');
-require('mappers/users_mapper');
-require('mappers/service_mapper');
-require('mappers/service_metrics_mapper');
-require('mappers/target_cluster_mapper');
-require('mappers/dataset_mapper');
-require('mappers/component_config_mapper');
-require('mappers/jobs/hive_jobs_mapper');
+require('mappers');
+
 require('mappers/jobs/hive_job_mapper');
 require('utils/http_client');
 require('utils/host_progress_popup');

+ 34 - 0
ambari-web/app/mappers.js

@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//load all mappers
+require('mappers/server_data_mapper');
+require('mappers/stack_service_component_mapper');
+require('mappers/status_mapper');
+require('mappers/hosts_mapper');
+require('mappers/cluster_mapper');
+require('mappers/jobs_mapper');
+require('mappers/runs_mapper');
+require('mappers/racks_mapper');
+require('mappers/users_mapper');
+require('mappers/service_mapper');
+require('mappers/service_metrics_mapper');
+require('mappers/target_cluster_mapper');
+require('mappers/dataset_mapper');
+require('mappers/component_config_mapper');
+require('mappers/jobs/hive_jobs_mapper');

+ 44 - 0
ambari-web/app/mappers/stack_service_component_mapper.js

@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.stackServiceComponentMapper = App.QuickDataMapper.create({
+  model: App.StackServiceComponent,
+  config: {
+    id: 'component_name',
+    component_name: 'component_name',
+    service_name: 'service_name',
+    component_category: 'component_category',
+    is_master: 'is_master',
+    is_client: 'is_client',
+    stack_name: 'stack_name',
+    stack_version: 'stack_version'
+  },
+
+  map: function (json) {
+    var model = this.get('model');
+    if (json.items) {
+      var result = [];
+      json.items.forEach(function (item) {
+        result.push(this.parseIt(item, this.config));
+      }, this);
+      App.store.loadMany(model, result);
+    }
+  }
+});

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

@@ -24,6 +24,7 @@ require('models/authentication');
 require('models/cluster');
 require('models/cluster_states');
 require('models/hosts');
+require('models/stack_service_component');
 require('models/quick_links');
 require('models/service');
 require('models/service_config');

+ 72 - 0
ambari-web/app/models/stack_service_component.js

@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+/**
+ * This model loads all serviceComponents supported by the stack
+ * @type {*}
+ */
+App.StackServiceComponent = DS.Model.extend({
+  componentName: DS.attr('string'),
+  serviceName: DS.attr('string'),
+  componentCategory: DS.attr('string'),
+  isMaster: DS.attr('boolean'),
+  isClient: DS.attr('boolean'),
+  stackName: DS.attr('string'),
+  stackVersion: DS.attr('string'),
+
+  displayName: function() {
+    return App.format.components[this.get('componentName')];
+  }.property('componentName'),
+
+  isSlave: function() {
+   return this.get('componentCategory') === 'SLAVE';
+  }.property('componentCategory'),
+
+  isRestartable: function() {
+    return !this.get('isClient');
+  }.property('isClient'),
+
+  isReassignable: function() {
+    return ['NAMENODE', 'SECONDARY_NAMENODE', 'JOBTRACKER', 'RESOURCEMANAGER'].contains(this.get('componentName'));
+  }.property('componentName'),
+
+  isDeletable: function() {
+    return ['SUPERVISOR', 'HBASE_MASTER', 'DATANODE', 'TASKTRACKER', 'NODEMANAGER', 'HBASE_REGIONSERVER'].contains(this.get('componentName'));
+  }.property('componentName'),
+
+  isRollinRestartAllowed: function() {
+    return ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "SUPERVISOR"].contains(this.get('componentName'));
+  }.property('componentName'),
+
+  isDecommissionAllowed: function() {
+    return ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER"].contains(this.get('componentName'));
+  }.property('componentName'),
+
+  isAddableToHost: function() {
+    return ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "HBASE_MASTER", "ZOOKEEPER_SERVER", "SUPERVISOR"].contains(this.get('componentName'));
+  }.property('componentName'),
+
+  isShownOnInstallerAssignMasterPage: function() {
+    var component = this.get('componentName');
+    var mastersNotShown = ['MYSQL_SERVER','JOURNALNODE'];
+    return ((this.get('isMaster') && !mastersNotShown.contains(component)) || component === 'APP_TIMELINE_SERVER');
+  }.property('isMaster','componentName')
+});
+
+App.StackServiceComponent.FIXTURES = [];

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

@@ -1231,12 +1231,12 @@ var urls = {
     }
   },
   'wizard.service_components': {
-    'real': '{stackUrl}/stackServices?fields=StackServices',
-    'mock': '/data/wizard/stack/hdp/version/{stackVersion}.json',
-    'format': function() {
+    'real': '{stackUrl}/stackServices?fields=StackServices/comments,StackServices/service_version,serviceComponents/*',
+    'mock': '/data/wizard/stacks/HDP-2.1/service_components.json',
+    'format': function(data) {
       return {
         timeout: 10000,
-        async: false
+        async: !!data.async
       };
     }
   },

+ 28 - 0
ambari-web/app/utils/component.js

@@ -20,6 +20,8 @@
  * Here will be stored slave functions related to components
  * @type {Object}
  */
+
+var App = require('app');
 module.exports = {
 
   /**
@@ -52,5 +54,31 @@ module.exports = {
     });
 
     return result;
+  },
+
+  /**
+   *
+   * @param data
+   */
+  loadStackServiceComponentModel: function(data) {
+    var serviceComponents = {items: []};
+    data.items.forEach(function(item){
+      item.serviceComponents.forEach(function(_serviceComponent){
+        var stackServiceComponents =  _serviceComponent.StackServiceComponents;
+        var serviceComponent = {
+          component_name: stackServiceComponents.component_name,
+          service_name: stackServiceComponents.service_name,
+          component_category: stackServiceComponents.component_category,
+          is_master: stackServiceComponents.is_master,
+          is_client: stackServiceComponents.is_client,
+          stack_name: stackServiceComponents.stack_name,
+          stack_version: stackServiceComponents.stack_version
+        };
+        serviceComponents.items.pushObject(serviceComponent);
+      },this);
+    },this);
+    App.stackServiceComponentMapper.map(serviceComponents);
+    App.handleStackDependedComponents();
+    return serviceComponents;
   }
 };

+ 1 - 1
ambari-web/app/views/main/host/summary.js

@@ -238,7 +238,7 @@ App.MainHostSummaryView = Em.View.extend({
       return [];
     }
     var componentServiceMap = App.QuickDataMapper.componentServiceMap();
-    var allClients = App.get('components.clients');
+    var allClients = App.StackServiceComponent.find().filterProperty('isClient',true).mapProperty('componentName');
     var installedServices = this.get('installedServices');
     var installedClients = this.get('clients').mapProperty('componentName');
     return allClients.filter(function(componentName) {

+ 6 - 35
ambari-web/test/app_test.js

@@ -19,31 +19,12 @@
 var App = require('app');
 
 describe('#App', function() {
+  describe('Disable/enable components', function() {
 
-  describe('App.components', function() {
-
-    it('slaves and masters should not intersect', function() {
-      var intersected = App.get('components.slaves').filter(function(item){
-        return App.get('components.masters').contains(item);
-      });
-      expect(intersected).to.eql([]);
-    });
-
-    it('decommissionAllowed', function() {
-      expect(App.get('components.decommissionAllowed')).to.eql(["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER"]);
-    });
-
-    it('addableToHost', function() {
-      expect(App.get('components.addableToHost')).to.eql(["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "HBASE_MASTER", "ZOOKEEPER_SERVER", "SUPERVISOR"]);
+    var testableComponent =  Ember.Object.create({
+      componentName: 'APP_TIMELINE_SERVER',
+      serviceName: 'YARN'
     });
-
-  });
-
-  describe('Disable/enable components', function() {
-    var testableComponent =  {
-      service_name: 'YARN',
-      component_name: 'APP_TIMELINE_SERVER'
-    };
     var expectedInfo = {
       componentName: 'APP_TIMELINE_SERVER',
       properties: {
@@ -59,7 +40,6 @@ describe('#App', function() {
     };
     var globalProperties = require('data/HDP2/global_properties');
     var siteProperties = require('data/HDP2/site_properties');
-    var serviceComponents = require('data/service_components');
     var reviewConfigs = require('data/review_configs');
     var disableResult;
 
@@ -71,7 +51,6 @@ describe('#App', function() {
       // copy
       var _globalProperties = $.extend({}, globalProperties);
       var _siteProperties = $.extend({}, siteProperties);
-      var _serviceComponents = $.extend({}, serviceComponents);
       var _reviewConfigs = JSON.parse(JSON.stringify(reviewConfigs));
 
       describe('result validation', function() {
@@ -103,9 +82,6 @@ describe('#App', function() {
 
       describe('effect validation',function() {
 
-        it('should remove component from service_components object', function() {
-          expect(_serviceComponents.findProperty('component_name', testableComponent.component_name)).to.be.undefined;
-        });
 
         it('should remove global properties of component', function() {
           expect(_globalProperties.configProperties.mapProperty('name')).to.not.include.members(expectedInfo.properties.global_properties);
@@ -117,7 +93,7 @@ describe('#App', function() {
 
         it('should remove review config for component', function() {
           var reviewConfig = _reviewConfigs.findProperty('config_name', 'services')
-            .config_value.findProperty('service_name', testableComponent.service_name)
+            .config_value.findProperty('service_name', testableComponent.get('serviceName'))
             .service_components.mapProperty('component_name');
           expect(reviewConfig).to.not.include(expectedInfo.reviewConfigs.component_name);
         });
@@ -127,10 +103,6 @@ describe('#App', function() {
     describe('#enableComponent', function() {
       App.enableComponent(disableResult);
 
-      it('should add component to service_components object', function() {
-        expect(serviceComponents.findProperty('component_name', testableComponent.component_name)).to.exist;
-      });
-
       it('should add global properties of component', function() {
         expect(globalProperties.configProperties.mapProperty('name')).to.include.members(expectedInfo.properties.global_properties);
       });
@@ -141,11 +113,10 @@ describe('#App', function() {
 
       it('should add review config for component', function() {
         var reviewConfig = reviewConfigs.findProperty('config_name', 'services')
-          .config_value.findProperty('service_name', testableComponent.service_name)
+          .config_value.findProperty('service_name', testableComponent.get('serviceName'))
           .get('service_components').mapProperty('component_name');
         expect(reviewConfig).to.include(expectedInfo.reviewConfigs.component_name);
       });
     });
   });
-
 });

+ 0 - 1
ambari-web/test/installer/step5_test.js

@@ -19,7 +19,6 @@
 var Ember = require('ember');
 var App = require('app');
 require('controllers/wizard/step5_controller');
-var components = require('data/service_components');
 
 describe('App.WizardStep5Controller', function () {
   var controller = App.WizardStep5Controller.create();

+ 3 - 1
ambari-web/test/installer/step6_test.js

@@ -23,7 +23,6 @@ require('controllers/wizard/step6_controller');
 describe('App.WizardStep6Controller', function () {
 
   var controller = App.WizardStep6Controller.create();
-
   controller.set('content', {
     hosts: {},
     masterComponentHosts: {},
@@ -46,6 +45,9 @@ describe('App.WizardStep6Controller', function () {
       })
     ]
   });
+  controller.set('getComponentDisplayName',function () {
+    return true;
+  });
 
   var HOSTS = Em.A([ 'host0', 'host1', 'host2', 'host3' ]);
 

+ 60 - 0
ambari-web/test/installer/step9_test.js

@@ -19,11 +19,71 @@
 
 var Ember = require('ember');
 var App = require('app');
+require('models/stack_service_component');
 require('models/hosts');
 require('controllers/wizard/step9_controller');
 require('utils/helper');
 
 describe('App.InstallerStep9Controller', function () {
+  var data = [
+    {
+      id: 'DATANODE',
+      component_name: 'DATANODE',
+      service_name: 'HDFS',
+      is_client: false,
+      is_master: false,
+      component_category: 'SLAVE'
+    },
+    {
+      id: 'TASKTRACKER',
+      component_name: 'TASKTRACKER',
+      service_name: 'MAPREDUCE',
+      is_client: false,
+      is_master: false,
+      component_category: 'SLAVE'
+    },
+    {
+      id: 'HBASE_REGIONSERVER',
+      component_name: 'HBASE_REGIONSERVER',
+      service_name: 'HBASE',
+      is_client: false,
+      is_master: false,
+      component_category: 'SLAVE'
+    },
+    {
+      id: 'GANGLIA_MONITOR',
+      component_name: 'GANGLIA_MONITOR',
+      service_name: 'GANGLIA',
+      is_client: false,
+      is_master: false,
+      component_category: 'SLAVE'
+    },
+    {
+      id: 'SUPERVISOR',
+      component_name: 'SUPERVISOR',
+      service_name: 'STORM',
+      is_client: false,
+      is_master: false,
+      component_category: 'SLAVE'
+    },
+    {
+      id: 'NAMENODE',
+      component_name: 'NAMENODE',
+      service_name: 'HDFS',
+      is_client: false,
+      is_master: true,
+      component_category: 'MASTER'
+    },
+    {
+      id: 'HDFS_CLIENT',
+      component_name: 'HDFS_CLIENT',
+      service_name: 'HDFS',
+      is_client: true,
+      is_master: false,
+      component_category: 'SLAVE'
+    }
+  ];
+  App.store.loadMany(App.StackServiceComponent,data);
 
   describe('#isSubmitDisabled', function () {
     var tests = Em.A([