Browse Source

AMBARI-14724. Provide option to +Add Oozie Server in Service Actions menu (akovalenko)

Aleksandr Kovalenko 9 years ago
parent
commit
8b7aa920bb

+ 100 - 76
ambari-web/app/controllers/main/service/item.js

@@ -44,6 +44,20 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
     }
     }
   },
   },
 
 
+  /**
+   * Map of service names and lists of sites they need to load
+   */
+  serviceConfigsMap: {
+    'OOZIE': ['oozie-env']
+  },
+
+  /**
+   * Configs loaded to use for service actions menu
+   *
+   * format: {config-type: {property-name1: property-value1, property-name2: property-value2, ...}}
+   */
+  configs: {},
+
   /**
   /**
    * @type {boolean}
    * @type {boolean}
    * @default true
    * @default true
@@ -56,42 +70,11 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
    */
    */
   isServicesInfoLoaded: false,
   isServicesInfoLoaded: false,
 
 
-  initHosts: function() {
-    if (App.get('components.masters').length !== 0) {
-      ['HBASE_MASTER', 'HIVE_METASTORE', 'ZOOKEEPER_SERVER', 'FLUME_HANDLER', 'HIVE_SERVER', 'RANGER_KMS_SERVER', 'NIMBUS'].forEach(function(componentName) {
-        this.loadHostsWithoutComponent(componentName);
-      }, this);
-    }
-  }.observes('App.components.masters', 'content.hostComponents.length'),
-
-  loadHostsWithoutComponent: function (componentName) {
-    var self = this;
-    var hostsWithComponent = App.HostComponent.find().filterProperty('componentName', componentName).mapProperty('hostName');
-
-    var hostsWithoutComponent = App.get('allHostNames').filter(function(hostName) {
-      return !hostsWithComponent.contains(hostName);
-    });
-
-    self.set('add' + componentName, function() {
-      App.get('router.mainAdminKerberosController').getKDCSessionState(function() {
-        self.addComponent(componentName);
-      });
-    });
-
-    Em.defineProperty(self, 'addDisabledTooltip-' + componentName, Em.computed('isAddDisabled-' + componentName, 'addDisabledMsg-' + componentName, function() {
-      if (self.get('isAddDisabled-' + componentName)) {
-        return self.get('addDisabledMsg-' + componentName);
-      }
-    }));
-
-    Em.defineProperty(self, 'isAddDisabled-' + componentName, Em.computed('hostsWithoutComponent-' + componentName, function() {
-      return self.get('hostsWithoutComponent-' + componentName).length === 0 ? 'disabled' : '';
-    }));
-
-    var disabledMsg = Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(componentName);
-    self.set('hostsWithoutComponent-' + componentName, hostsWithoutComponent);
-    self.set('addDisabledMsg-' + componentName, disabledMsg);
-  },
+  /**
+   * Define whether configs for service actions menu were loaded
+   * @type {Boolean}
+   */
+  isServiceConfigsLoaded: false,
 
 
   /**
   /**
    * flag to control router switch between service summary and configs
    * flag to control router switch between service summary and configs
@@ -122,6 +105,48 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
     return clientNames;
     return clientNames;
   }.property('content.serviceName'),
   }.property('content.serviceName'),
 
 
+  /**
+   * Load all config tags for loading configs
+   */
+  loadConfigs: function(){
+    if (this.get('serviceConfigsMap')[this.get('content.serviceName')]) {
+      this.set('isServiceConfigsLoaded', false);
+      App.ajax.send({
+        name: 'config.tags',
+        sender: this,
+        success: 'onLoadConfigsTags',
+        error: 'onTaskError'
+      });
+    } else {
+      this.set('isServiceConfigsLoaded', true);
+    }
+  },
+
+  /**
+   * Load all configs for sites from <code>serviceConfigsMap</code> for current service
+   * @param data
+   */
+  onLoadConfigsTags: function (data) {
+    var self = this;
+    var sitesToLoad = this.get('serviceConfigsMap')[this.get('content.serviceName')];
+    var loadedSites = data.Clusters.desired_configs;
+    var siteTagsToLoad = [];
+    for (var site in loadedSites) {
+      if (sitesToLoad.contains(site)) {
+        siteTagsToLoad.push({
+          siteName: site,
+          tagName: loadedSites[site].tag
+        });
+      }
+    }
+    App.router.get('configurationController').getConfigsByTags(siteTagsToLoad).done(function (configs) {
+      configs.forEach(function (site) {
+        self.get('configs')[site.type] = site.properties;
+      });
+      self.set('isServiceConfigsLoaded', true);
+    });
+  },
+
   /**
   /**
    * Common method for ajax (start/stop service) responses
    * Common method for ajax (start/stop service) responses
    * @param data
    * @param data
@@ -779,60 +804,59 @@ App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDow
     var component = App.StackServiceComponent.find().findProperty('componentName', componentName);
     var component = App.StackServiceComponent.find().findProperty('componentName', componentName);
     var componentDisplayName = component.get('displayName');
     var componentDisplayName = component.get('displayName');
 
 
-    self.loadHostsWithoutComponent(componentName);
+    App.get('router.mainAdminKerberosController').getKDCSessionState(function () {
+      return App.ModalPopup.show({
+        primary: Em.computed.ifThenElse('anyHostsWithoutComponent', Em.I18n.t('hosts.host.addComponent.popup.confirm'), undefined),
 
 
-    return App.ModalPopup.show({
-      primary: Em.computed.ifThenElse('anyHostsWithoutComponent', Em.I18n.t('hosts.host.addComponent.popup.confirm'), undefined),
+        header: Em.I18n.t('popup.confirmation.commonHeader'),
 
 
-      header: Em.I18n.t('popup.confirmation.commonHeader'),
+        addComponentMsg: Em.I18n.t('hosts.host.addComponent.msg').format(componentDisplayName),
 
 
-      addComponentMsg: Em.I18n.t('hosts.host.addComponent.msg').format(componentDisplayName),
+        selectHostMsg: Em.computed.i18nFormat('services.summary.selectHostForComponent', 'componentDisplayName'),
 
 
-      selectHostMsg: Em.computed.i18nFormat('services.summary.selectHostForComponent', 'componentDisplayName'),
+        thereIsNoHostsMsg: Em.computed.i18nFormat('services.summary.allHostsAlreadyRunComponent', 'componentDisplayName'),
 
 
-      thereIsNoHostsMsg: Em.computed.i18nFormat('services.summary.allHostsAlreadyRunComponent', 'componentDisplayName'),
+        hostsWithoutComponent: function () {
+          var hostsWithComponent = App.HostComponent.find().filterProperty('componentName', componentName).mapProperty('hostName');
+          var result = App.get('allHostNames');
 
 
-      hostsWithoutComponent: function() {
-        return self.get("hostsWithoutComponent-" + this.get('componentName'));
-      }.property('componentName', 'self.hostsWithoutComponent-' + this.get('componentName')),
+          hostsWithComponent.forEach(function (host) {
+            result = result.without(host);
+          });
 
 
-      anyHostsWithoutComponent: Em.computed.gt('hostsWithoutComponent.length', 0),
+          return result;
+        }.property(),
 
 
-      selectedHost: null,
+        anyHostsWithoutComponent: Em.computed.gt('hostsWithoutComponent.length', 0),
 
 
-      componentName: componentName,
+        selectedHost: null,
 
 
-      componentDisplayName: componentDisplayName,
+        componentName: componentName,
 
 
-      bodyClass: Em.View.extend({
-        templateName: require('templates/main/service/add_host_popup')
-      }),
+        componentDisplayName: componentDisplayName,
 
 
-      onPrimary: function () {
-        var selectedHost = this.get('selectedHost');
-
-        // Install
-        if(['HIVE_METASTORE', 'RANGER_KMS_SERVER', 'NIMBUS'].contains(component.get('componentName')) && !!selectedHost){
-          App.router.get('mainHostDetailsController').addComponentWithCheck(
-            {
-              context: component,
-              selectedHost: selectedHost
-            }
-          );
-        } else {
-          self.installHostComponentCall(selectedHost, component);
-        }
+        bodyClass: Em.View.extend({
+          templateName: require('templates/main/service/add_host_popup')
+        }),
 
 
-        // Remove host from 'without' collection to immediate recalculate add menu item state
-        var hostsWithoutComponent = this.get('hostsWithoutComponent');
-        var index = hostsWithoutComponent.indexOf(this.get('selectedHost'));
-        if (index > -1) {
-          hostsWithoutComponent.splice(index, 1);
-        }
+        onPrimary: function () {
+          var selectedHost = this.get('selectedHost');
 
 
-        self.set('hostsWithoutComponent-' + this.get('componentName'), hostsWithoutComponent);
-        this.hide();
-      }
+          // Install
+          if (['HIVE_METASTORE', 'RANGER_KMS_SERVER', 'NIMBUS'].contains(component.get('componentName')) && !!selectedHost) {
+            App.router.get('mainHostDetailsController').addComponentWithCheck(
+                {
+                  context: component,
+                  selectedHost: selectedHost
+                }
+            );
+          } else {
+            self.installHostComponentCall(selectedHost, component);
+          }
+
+          this.hide();
+        }
+      });
     });
     });
   },
   },
 
 

+ 4 - 0
ambari-web/app/mixins/common/configs/configs_saver.js

@@ -619,6 +619,10 @@ App.ConfigsSaverMixin = Em.Mixin.create({
       App.QuickViewLinks.proto().set('content', currentService);
       App.QuickViewLinks.proto().set('content', currentService);
       App.QuickViewLinks.proto().loadTags();
       App.QuickViewLinks.proto().loadTags();
     }
     }
+
+    //  update configs for service actions
+    App.router.get('mainServiceItemController').loadConfigs();
+
     this.showSaveConfigsPopup(header, flag, message, messageClass, value, status, urlParams);
     this.showSaveConfigsPopup(header, flag, message, messageClass, value, status, urlParams);
     this.clearAllRecommendations();
     this.clearAllRecommendations();
   },
   },

+ 68 - 52
ambari-web/app/views/main/service/item.js

@@ -41,52 +41,58 @@ App.MainServiceItemView = Em.View.extend({
 
 
    addActionMap: function() {
    addActionMap: function() {
      return [
      return [
-      {
-        cssClass: 'icon-plus',
-        'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.hbase.masterServer')),
-        service: 'HBASE',
-        component: 'HBASE_MASTER'
-      },
-      {
-       cssClass: 'icon-plus',
-       'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.hive.metastore')),
-       service: 'HIVE',
-       component: 'HIVE_METASTORE',
-       isHidden: !App.get('isHadoop22Stack')
-      },
-      {
-       cssClass: 'icon-plus',
-       'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.hive.server2')),
-       service: 'HIVE',
-       component: 'HIVE_SERVER',
-       isHidden: !App.get('isHadoop22Stack')
-      },
-      {
-        cssClass: 'icon-plus',
-        'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.zookeeper.server')),
-        service: 'ZOOKEEPER',
-        component: 'ZOOKEEPER_SERVER'
-      },
-      {
-        cssClass: 'icon-plus',
-        'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.flume.agentLabel')),
-        service: 'FLUME',
-        component: 'FLUME_HANDLER'
-      },
-      {
-        cssClass: 'icon-plus',
-        'label': '{0} {1}'.format(Em.I18n.t('add'), App.format.role('RANGER_KMS_SERVER')),
-        service: 'RANGER_KMS',
-        component: 'RANGER_KMS_SERVER'
-      },
-      {
-        cssClass: 'icon-plus',
-        'label': '{0} {1}'.format(Em.I18n.t('add'), App.format.role('NIMBUS')),
-        service: 'STORM',
-        component: 'NIMBUS'
-      }
-    ]
-  },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.hbase.masterServer')),
+         service: 'HBASE',
+         component: 'HBASE_MASTER'
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.hive.metastore')),
+         service: 'HIVE',
+         component: 'HIVE_METASTORE',
+         isHidden: !App.get('isHadoop22Stack')
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.hive.server2')),
+         service: 'HIVE',
+         component: 'HIVE_SERVER',
+         isHidden: !App.get('isHadoop22Stack')
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.zookeeper.server')),
+         service: 'ZOOKEEPER',
+         component: 'ZOOKEEPER_SERVER'
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), Em.I18n.t('dashboard.services.flume.agentLabel')),
+         service: 'FLUME',
+         component: 'FLUME_HANDLER'
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), App.format.role('RANGER_KMS_SERVER')),
+         service: 'RANGER_KMS',
+         component: 'RANGER_KMS_SERVER'
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), App.format.role('NIMBUS')),
+         service: 'STORM',
+         component: 'NIMBUS'
+       },
+       {
+         cssClass: 'icon-plus',
+         'label': '{0} {1}'.format(Em.I18n.t('add'), App.format.role('OOZIE_SERVER')),
+         service: 'OOZIE',
+         component: 'OOZIE_SERVER'
+       }
+     ]
+   },
   /**
   /**
    * Create option for MOVE_COMPONENT or ROLLING_RESTART task.
    * Create option for MOVE_COMPONENT or ROLLING_RESTART task.
    *
    *
@@ -103,7 +109,7 @@ App.MainServiceItemView = Em.View.extend({
   isMaintenanceSet: false,
   isMaintenanceSet: false,
 
 
   observeMaintenance: function() {
   observeMaintenance: function() {
-    if (!this.get('isMaintenanceSet') && this.get('controller.isServicesInfoLoaded')) {
+    if (!this.get('isMaintenanceSet') && this.get('controller.isServicesInfoLoaded') && this.get('controller.isServiceConfigsLoaded')) {
       this.observeMaintenanceOnce();
       this.observeMaintenanceOnce();
     }
     }
     Em.run.once(this, 'clearIsMaintenanceSet');
     Em.run.once(this, 'clearIsMaintenanceSet');
@@ -200,15 +206,24 @@ App.MainServiceItemView = Em.View.extend({
               component: hawqMasterComponent.get('componentName'),
               component: hawqMasterComponent.get('componentName'),
               command: customCommandToStopCluster
               command: customCommandToStopCluster
             }
             }
-          }))
+          }));
         }
         }
       }
       }
 
 
       self.addActionMap().filterProperty('service', serviceName).forEach(function(item) {
       self.addActionMap().filterProperty('service', serviceName).forEach(function(item) {
         if (App.get('components.addableToHost').contains(item.component)) {
         if (App.get('components.addableToHost').contains(item.component)) {
-          item.action = 'add' + item.component;
-          item.disabled = self.get('controller.isAddDisabled-' + item.component);
-          item.tooltip = self.get('controller.addDisabledTooltip' + item.component);
+
+          var isEnabled = App.HostComponent.find().filterProperty('componentName', item.component).length < App.get('allHostNames.length');
+
+          if (item.component === 'OOZIE_SERVER') {
+            isEnabled = isEnabled && !(Em.isEmpty(self.get('controller.configs.oozie-env.oozie_database')) || self.get('controller.configs.oozie-env.oozie_database') === 'New Derby Database');
+          }
+
+          item.action = 'addComponent';
+          item.disabled = isEnabled ? '' : 'disabled';
+          item.tooltip = isEnabled ? '' : Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(item.component);
+          item.context = item.component;
+
           options.push(item);
           options.push(item);
         }
         }
       });
       });
@@ -282,10 +297,11 @@ App.MainServiceItemView = Em.View.extend({
     this.get('controller').setStartStopState();
     this.get('controller').setStartStopState();
   },
   },
 
 
-  maintenanceObsFields: ['isStopDisabled', 'isClientsOnlyService', 'content.isRestartRequired', 'isServicesInfoLoaded'],
+  maintenanceObsFields: ['isStopDisabled', 'isClientsOnlyService', 'content.isRestartRequired', 'isServicesInfoLoaded', 'isServiceConfigsLoaded'],
 
 
   willInsertElement: function () {
   willInsertElement: function () {
     var self = this;
     var self = this;
+    this.get('controller').loadConfigs();
     this.get('maintenanceObsFields').forEach(function (field) {
     this.get('maintenanceObsFields').forEach(function (field) {
       self.addObserver('controller.' + field, self, 'observeMaintenance');
       self.addObserver('controller.' + field, self, 'observeMaintenance');
     });
     });

+ 12 - 4
ambari-web/test/views/main/service/item_test.js

@@ -84,24 +84,28 @@ describe('App.MainServiceItemView', function () {
       {
       {
         isMaintenanceSet: true,
         isMaintenanceSet: true,
         isServicesInfoLoaded: true,
         isServicesInfoLoaded: true,
+        isServiceConfigsLoaded: true,
         observeMaintenanceOnceCallCount: 0,
         observeMaintenanceOnceCallCount: 0,
         title: 'actions array set, services info loaded'
         title: 'actions array set, services info loaded'
       },
       },
       {
       {
         isMaintenanceSet: true,
         isMaintenanceSet: true,
         isServicesInfoLoaded: false,
         isServicesInfoLoaded: false,
+        isServiceConfigsLoaded: true,
         observeMaintenanceOnceCallCount: 0,
         observeMaintenanceOnceCallCount: 0,
         title: 'actions array set, services info not loaded'
         title: 'actions array set, services info not loaded'
       },
       },
       {
       {
         isMaintenanceSet: false,
         isMaintenanceSet: false,
         isServicesInfoLoaded: true,
         isServicesInfoLoaded: true,
+        isServiceConfigsLoaded: true,
         observeMaintenanceOnceCallCount: 1,
         observeMaintenanceOnceCallCount: 1,
         title: 'actions array not set, services info loaded'
         title: 'actions array not set, services info loaded'
       },
       },
       {
       {
         isMaintenanceSet: false,
         isMaintenanceSet: false,
         isServicesInfoLoaded: false,
         isServicesInfoLoaded: false,
+        isServiceConfigsLoaded: true,
         observeMaintenanceOnceCallCount: 0,
         observeMaintenanceOnceCallCount: 0,
         title: 'actions array not set, services info not loaded'
         title: 'actions array not set, services info not loaded'
       }
       }
@@ -119,7 +123,8 @@ describe('App.MainServiceItemView', function () {
       it(item.title, function () {
       it(item.title, function () {
         view.setProperties({
         view.setProperties({
           'isMaintenanceSet': item.isMaintenanceSet,
           'isMaintenanceSet': item.isMaintenanceSet,
-          'controller.isServicesInfoLoaded': item.isServicesInfoLoaded
+          'controller.isServicesInfoLoaded': item.isServicesInfoLoaded,
+          'controller.isServiceConfigsLoaded': item.isServiceConfigsLoaded
         });
         });
         view.observeMaintenance();
         view.observeMaintenance();
         expect(view.observeMaintenanceOnce.callCount).to.equal(item.observeMaintenanceOnceCallCount);
         expect(view.observeMaintenanceOnce.callCount).to.equal(item.observeMaintenanceOnceCallCount);
@@ -206,7 +211,7 @@ describe('App.MainServiceItemView', function () {
             {"action": "restartAllHostComponents", "context": "ZOOKEEPER", "label": "Restart All", "cssClass": "icon-repeat", "disabled": false},
             {"action": "restartAllHostComponents", "context": "ZOOKEEPER", "label": "Restart All", "cssClass": "icon-repeat", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for ZooKeeper", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for ZooKeeper", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
-            {"cssClass": "icon-plus", "label": "Add ZooKeeper Server", "service": "ZOOKEEPER", "component": "ZOOKEEPER_SERVER", "action": "addZOOKEEPER_SERVER", "disabled": "disabled", tooltip: ''},
+            {"cssClass": "icon-plus", "label": "Add ZooKeeper Server", "service": "ZOOKEEPER", "component": "ZOOKEEPER_SERVER", "action": "addComponent", "disabled": "", tooltip: ''},
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": false, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": false, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
           ]
           ]
         },
         },
@@ -319,7 +324,7 @@ describe('App.MainServiceItemView', function () {
             {"action": "rollingRestart", "label": "Restart Flumes", "cssClass": "icon-time", "disabled": false, "context": "FLUME_HANDLER"},
             {"action": "rollingRestart", "label": "Restart Flumes", "cssClass": "icon-time", "disabled": false, "context": "FLUME_HANDLER"},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for Flume", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for Flume", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
-            {"cssClass": "icon-plus", "label": "Add Flume Component", "service": "FLUME", "component": "FLUME_HANDLER", "action": "addFLUME_HANDLER", "disabled": '', tooltip: ''},
+            {"cssClass": "icon-plus", "label": "Add Flume Component", "service": "FLUME", "component": "FLUME_HANDLER", "action": "addComponent", "disabled": '', tooltip: ''},
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": true, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": true, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
           ]
           ]
         },
         },
@@ -355,7 +360,7 @@ describe('App.MainServiceItemView', function () {
             {"action": "rollingRestart", "label": "Restart RegionServers", "cssClass": "icon-time", "disabled": false, "context": "HBASE_REGIONSERVER"},
             {"action": "rollingRestart", "label": "Restart RegionServers", "cssClass": "icon-time", "disabled": false, "context": "HBASE_REGIONSERVER"},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for HBase", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for HBase", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
-            {"cssClass": "icon-plus", "label": "Add HBase Master", "service": "HBASE", "component": "HBASE_MASTER", "action": "addHBASE_MASTER", "disabled": '', tooltip: ''},
+            {"cssClass": "icon-plus", "label": "Add HBase Master", "service": "HBASE", "component": "HBASE_MASTER", "action": "addComponent", "disabled": '', tooltip: ''},
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": false, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": false, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
           ]
           ]
         },
         },
@@ -382,6 +387,7 @@ describe('App.MainServiceItemView', function () {
             {"action": "reassignMaster", "context": "OOZIE_SERVER", "label": "Move Oozie Server", "cssClass": "icon-share-alt", "disabled": false},
             {"action": "reassignMaster", "context": "OOZIE_SERVER", "label": "Move Oozie Server", "cssClass": "icon-share-alt", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "runSmokeTest", "label": "Run Service Check", "cssClass": "icon-thumbs-up-alt", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for Oozie", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
             {"action": "turnOnOffPassive", "context": "Turn On Maintenance Mode for Oozie", "label": "Turn On Maintenance Mode", "cssClass": "icon-medkit", "disabled": false},
+            {"cssClass": "icon-plus", "label": "Add Oozie Server", "service": "OOZIE", "component": "OOZIE_SERVER", "action": "addComponent", "disabled": "disabled", tooltip: Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format('OOZIE_SERVER')},
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": false, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
             {"action": "downloadClientConfigs", "label": "Download Client Configs", "cssClass": "icon-download-alt", "isHidden": false, "disabled": false, "hasSubmenu": false, "submenuOptions": []}
           ]
           ]
         },
         },
@@ -449,6 +455,8 @@ describe('App.MainServiceItemView', function () {
             return ["HDFS", "MAPREDUCE2", "YARN", "HIVE", "HBASE", "PIG", "SQOOP", "OOZIE", "ZOOKEEPER", "FALCON", "STORM", "FLUME", "SLIDER", "KNOX", "KAFKA"];
             return ["HDFS", "MAPREDUCE2", "YARN", "HIVE", "HBASE", "PIG", "SQOOP", "OOZIE", "ZOOKEEPER", "FALCON", "STORM", "FLUME", "SLIDER", "KNOX", "KAFKA"];
           case 'components.addableToHost':
           case 'components.addableToHost':
             return ["DATANODE", "HDFS_CLIENT", "MAPREDUCE2_CLIENT", "NODEMANAGER", "YARN_CLIENT", "TEZ_CLIENT", "GANGLIA_MONITOR", "HCAT", "HIVE_CLIENT", "HIVE_METASTORE", "HIVE_SERVER", "WEBHCAT_SERVER", "HBASE_CLIENT", "HBASE_MASTER", "HBASE_REGIONSERVER", "PIG", "SQOOP", "OOZIE_CLIENT", "OOZIE_SERVER", "ZOOKEEPER_CLIENT", "ZOOKEEPER_SERVER", "FALCON_CLIENT", "SUPERVISOR", "FLUME_HANDLER", "METRICS_MONITOR", "KAFKA_BROKER", "KERBEROS_CLIENT", "KNOX_GATEWAY", "SLIDER", "SPARK_CLIENT"];
             return ["DATANODE", "HDFS_CLIENT", "MAPREDUCE2_CLIENT", "NODEMANAGER", "YARN_CLIENT", "TEZ_CLIENT", "GANGLIA_MONITOR", "HCAT", "HIVE_CLIENT", "HIVE_METASTORE", "HIVE_SERVER", "WEBHCAT_SERVER", "HBASE_CLIENT", "HBASE_MASTER", "HBASE_REGIONSERVER", "PIG", "SQOOP", "OOZIE_CLIENT", "OOZIE_SERVER", "ZOOKEEPER_CLIENT", "ZOOKEEPER_SERVER", "FALCON_CLIENT", "SUPERVISOR", "FLUME_HANDLER", "METRICS_MONITOR", "KAFKA_BROKER", "KERBEROS_CLIENT", "KNOX_GATEWAY", "SLIDER", "SPARK_CLIENT"];
+          case 'allHostNames.length':
+            return 2;
           default:
           default:
             return Em.get(App, k);
             return Em.get(App, k);
         }
         }