Ver Fonte

AMBARI-2079. Can't change service configuration if heartbeat lost from service component host. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/trunk@1479659 13f79535-47bb-0310-9956-ffa450edef68
Yusaku Sako há 12 anos atrás
pai
commit
61d1045d6b

+ 3 - 0
CHANGES.txt

@@ -828,6 +828,9 @@ Trunk (unreleased changes):
 
  BUG FIXES
 
+ AMBARI-2079. Can't change service configuration if heartbeat lost from
+ service component host. (yusaku)
+
  AMBARI-2075. Admin role can't be assigned to LDAP user. (yusaku)
 
  AMBARI-2080. Cluster name and Background operations indicator should

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

@@ -581,6 +581,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
 
   /**
    * Determines which host components are running on each host.
+   * @param status 'running' or 'unknown'
    * @return Returned in the following format:
    * {
    *  runningHosts: {
@@ -590,38 +591,38 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
    *  runningComponentCount: 5
    * }
    */
-  getRunningHostComponents: function (services) {
-    var runningHosts = [];
-    var runningComponentCount = 0;
+  getHostComponentsByStatus: function (services, status) {
+    var hosts = [];
+    var componentCount = 0;
     var hostToIndexMap = {};
     services.forEach(function (service) {
-      var runningHostComponents = service.get('runningHostComponents');
-      if (runningHostComponents != null) {
-        runningHostComponents.forEach(function (hc) {
+      var hostComponents = (status == App.HostComponentStatus.started) ? service.get('runningHostComponents') : service.get('unknownHostComponents');
+      if (hostComponents != null) {
+        hostComponents.forEach(function (hc) {
           var hostName = hc.get('host.publicHostName');
           var componentName = hc.get('displayName');
-          runningComponentCount++;
+          componentCount++;
           if (!(hostName in hostToIndexMap)) {
-            runningHosts.push({
+            hosts.push({
               name: hostName,
               components: ""
             });
-            hostToIndexMap[hostName] = runningHosts.length - 1;
+            hostToIndexMap[hostName] = hosts.length - 1;
           }
-          var hostObj = runningHosts[hostToIndexMap[hostName]];
+          var hostObj = hosts[hostToIndexMap[hostName]];
           if (hostObj.components.length > 0)
             hostObj.components += ", " + componentName;
           else
             hostObj.components += componentName;
         });
-        runningHosts.sort(function (a, b) {
+        hosts.sort(function (a, b) {
           return a.name.localeCompare(b.name);
         });
       }
     });
     return {
-      runningHosts: runningHosts,
-      runningComponentCount: runningComponentCount
+      hosts: hosts,
+      componentCount: componentCount
     };
   },
   
@@ -635,10 +636,13 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     var header;
     var message;
     var messageClass;
+    var hasUnknown = false;
     var value;
     var flag = false;
     var runningHosts = null;
     var runningComponentCount = 0;
+    var unknownHosts = null;
+    var unknownComponentCount = 0;
 
     var dfd = $.Deferred();
     var self = this;
@@ -649,6 +653,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
         (serviceName !== 'HDFS' && this.get('content.isStopped') === true) ||
         ((serviceName === 'HDFS') && this.get('content.isStopped') === true && (!App.Service.find().someProperty('id', 'MAPREDUCE') || App.Service.find('MAPREDUCE').get('isStopped')))) {
 
+      // warn the user if any service directories are being changed
       var dirChanged = false;
 
       if (serviceName === 'HDFS') {
@@ -686,6 +691,16 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
           header = Em.I18n.t('services.service.config.saved');
           message = Em.I18n.t('services.service.config.saved.message');
           messageClass = 'alert alert-success';
+          // warn the user if any of the components are in UNKNOWN state
+          var uhc;
+          if (self.get('content.serviceName') !== 'HDFS' || (self.get('content.serviceName') === 'HDFS' && !App.Service.find().someProperty('id', 'MAPREDUCE'))) {
+            uhc = self.getHostComponentsByStatus([self.get('content')], App.HostComponentStatus.unknown);
+          } else {
+            uhc = self.getHostComponentsByStatus([self.get('content'), App.Service.find('MAPREDUCE')], App.HostComponentStatus.unknown);
+          }
+          debugger;
+          unknownHosts = uhc.hosts;
+          unknownComponentCount = uhc.componentCount;
         } else {
           header = Em.I18n.t('common.failure');
           message = result.message;
@@ -696,17 +711,17 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
     } else {
       var rhc;
       if (this.get('content.serviceName') !== 'HDFS' || (this.get('content.serviceName') === 'HDFS' && !App.Service.find().someProperty('id', 'MAPREDUCE'))) {
-        rhc = this.getRunningHostComponents([this.get('content')]);
+        rhc = this.getHostComponentsByStatus([this.get('content')], App.HostComponentStatus.started);
         header = Em.I18n.t('services.service.config.notSaved');
         message = Em.I18n.t('services.service.config.msgServiceStop');
       } else {
-        rhc = this.getRunningHostComponents([this.get('content'), App.Service.find('MAPREDUCE')]);
+        rhc = this.getHostComponentsByStatus([this.get('content'), App.Service.find('MAPREDUCE')], App.HostComponentStatus.started);
         header = Em.I18n.t('services.service.config.notSaved');
         message = Em.I18n.t('services.service.config.msgHDFSMapRServiceStop');
       }
       messageClass = 'alert alert-error';
-      runningHosts = rhc.runningHosts;
-      runningComponentCount = rhc.runningComponentCount;
+      runningHosts = rhc.hosts;
+      runningComponentCount = rhc.componentCount;
       dfd.resolve();
     }
 
@@ -727,6 +742,8 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
           messageClass: messageClass,
           runningHosts: runningHosts,
           runningComponentCount: runningComponentCount,
+          unknownHosts: unknownHosts,
+          unknownComponentCount: unknownComponentCount,
           siteProperties: value,
           getDisplayMessage: function () {
             var displayMsg = [];
@@ -761,33 +778,16 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
             return displayMsg;
 
           }.property('siteProperties'),
-          getRunningHostsMessage: function () {
+
+          runningHostsMessage: function () {
             return Em.I18n.t('services.service.config.stopService.runningHostComponents').format(this.get('runningComponentCount'), this.get('runningHosts.length'));
           }.property('runningComponentCount', 'runningHosts.length'),
-          template: Ember.Handlebars.compile([
-            '<div class="{{unbound view.messageClass}}" style="margin-bottom:0">{{view.message}}</div>',
-            '{{#unless view.flag}}',
-            ' <br/>',
-            ' <div class="pre-scrollable" style="max-height: 250px;">',
-            '   <ul>',
-            '   {{#each val in view.getDisplayMessage}}',
-            '     <li>',
-            '       {{val}}',
-            '     </li>',
-            '   {{/each}}',
-            '   </ul>',
-            ' </div>',
-            '{{/unless}}',
-            '{{#if view.runningHosts}}',
-            ' <i class="icon-warning-sign"></i>  {{view.getRunningHostsMessage}}',
-            ' <table class="table-striped running-host-components-table">',
-            '   <tr><th>{{t common.host}}</th><th>{{t common.components}}</th></tr>',
-            '   {{#each host in view.runningHosts}}',
-            '     <tr><td>{{host.name}}</td><td>{{host.components}}</td></tr>',
-            '   {{/each}}',
-            ' </table>',
-            '{{/if}}'
-          ].join('\n'))
+
+          unknownHostsMessage: function () {
+            return Em.I18n.t('services.service.config.stopService.unknownHostComponents').format(this.get('unknownComponentCount'), this.get('unknownHosts.length'));
+          }.property('unknownComponentCount', 'unknownHosts.length'),
+
+          templateName: require('templates/main/service/info/configs_save_popup')
         })
       })
     });

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

@@ -734,10 +734,10 @@ Em.I18n.translations = {
   'services.service.info.summary.nagios.noAlerts':'No alerts',
   'services.service.info.summary.nagios.alerts':'Nagios service required for viewing alerts',
 
-  'services.service.config.saved':'Saved Configurations Changes',
+  'services.service.config.saved':'Saved Configuration Changes',
   'services.service.config.notSaved':'Unable to Save Configuration Changes',
   'services.service.config.restartService.TooltipMessage':'<b>Restart Service</b><br>Stale configuration used by {0} components on {1} hosts:{2}',
-  'services.service.config.saved.message':'Service configuration saved successfully.',
+  'services.service.config.saved.message':'Service configuration changes saved successfully.',
   'services.service.config.msgServiceStop':'Could not save configuration changes.  Please stop the service first. You will be able to save configuration changes after all of its components are stopped.',
   'services.service.config.msgHDFSMapRServiceStop':'Could not save configuration changes.  Please stop both HDFS and MapReduce first.  You will be able to save configuration changes after all HDFS and MapReduce components are stopped.',
   'services.service.config.failCreateConfig' : 'Failure in creating service configuration',
@@ -746,6 +746,7 @@ Em.I18n.translations = {
   'services.service.config.addPropertyWindow.errorMessage':'This is required',
   'services.service.config.addPropertyWindow.error.derivedKey':'This property is already defined',
   'services.service.config.stopService.runningHostComponents':'{0} components on {1} hosts are still running',
+  'services.service.config.stopService.unknownHostComponents':'{0} components on {1} hosts are in unknown state.  These components might actually be running and need restarting later to make the changes effective.',
   'services.service.config.confirmDirectoryChange':'You are about to make changes to service directories that are core to {0}. Before you proceed, be absolutely certain of the implications and that you have taken necessary manual steps, if any, for the changes. Are you sure you want to proceed?',
 
   'services.add.header':'Add Service Wizard',

+ 12 - 2
ambari-web/app/models/service.js

@@ -88,14 +88,23 @@ App.Service = DS.Model.extend({
   updateIsStopped: function () {
     var components = this.get('hostComponents');
     var flag = true;
-    var runningHCs = Ember.A([]);
+    var runningHCs = [];
+    var unknownHCs = [];
+    debugger;
     components.forEach(function (_component) {
-      if (_component.get('workStatus') !== App.HostComponentStatus.stopped && _component.get('workStatus') !== App.HostComponentStatus.install_failed) {
+      if (
+        _component.get('workStatus') !== App.HostComponentStatus.stopped &&
+        _component.get('workStatus') !== App.HostComponentStatus.install_failed &&
+        _component.get('workStatus') !== App.HostComponentStatus.unknown
+      ) {
         flag = false;
         runningHCs.addObject(_component);
+      } else if (_component.get('workStatus') == App.HostComponentStatus.unknown) {
+        unknownHCs.addObject(_component);
       }
     }, this);
     this.set('runningHostComponents', runningHCs);
+    this.set('unknownHostComponents', unknownHCs);
     this.set('isStopped', flag);
   },
 
@@ -105,6 +114,7 @@ App.Service = DS.Model.extend({
       components.everyProperty('workStatus', App.HostComponentStatus.started)
     );
   },
+
   isConfigurable: function () {
     var configurableServices = [
       "HDFS",

+ 2 - 1
ambari-web/app/styles/application.less

@@ -647,8 +647,9 @@ h1 {
 
 .running-host-components-table{
   width: 100%;
+  margin-top: 10px;
   text-align: left;
-  tbody{
+  tbody {
     vertical-align: top;
   }
 }

+ 48 - 0
ambari-web/app/templates/main/service/info/configs_save_popup.hbs

@@ -0,0 +1,48 @@
+{{!
+* 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.
+}}
+
+<div class="{{unbound view.messageClass}}">{{view.message}}</div>
+{{#unless view.flag}}
+  <div class="pre-scrollable" style="max-height: 250px;">
+    <ul>
+    {{#each val in view.getDisplayMessage}}
+      <li>
+        {{val}}
+      </li>
+    {{/each}}
+    </ul>
+  </div>
+{{/unless}}
+{{#if view.runningHosts}}
+  <i class="icon-warning-sign"></i>  {{view.runningHostsMessage}}
+  <table class="table-striped running-host-components-table">
+    <tr><th>{{t common.host}}</th><th>{{t common.components}}</th></tr>
+    {{#each host in view.runningHosts}}
+    <tr><td>{{host.name}}</td><td>{{host.components}}</td></tr>
+    {{/each}}
+  </table>
+{{/if}}
+{{#if view.unknownHosts}}
+  <i class="icon-warning-sign"></i>  {{view.unknownHostsMessage}}
+  <table class="table-striped running-host-components-table">
+    <tr><th>{{t common.host}}</th><th>{{t common.components}}</th></tr>
+    {{#each host in view.unknownHosts}}
+      <tr><td>{{host.name}}</td><td>{{host.components}}</td></tr>
+    {{/each}}
+  </table>
+{{/if}}