Ver código fonte

AMBARI-8696. Alerts UI: prompt for initial SMTP setup during install (onechiporenko via srimanth)

Srimanth Gunturi 10 anos atrás
pai
commit
12d13e8b07

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

@@ -720,6 +720,19 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
         });
         serviceConfigs.findProperty('serviceName', 'HDFS').configs = c;
       }
+
+      // Remove Notifications from MISC if it isn't Installer Controller
+      if (this.get('wizardController.name') !== 'installerController') {
+        var miscService = serviceConfigs.findProperty('serviceName', 'MISC');
+        if (miscService) {
+          c = miscService.configs;
+          removedConfigs = c.filterProperty('category', 'Notifications');
+          removedConfigs.map(function (config) {
+            c = c.without(config);
+          });
+          miscService.configs = c;
+        }
+      }
     }
 
     this.set('stepConfigs', serviceConfigs);

+ 54 - 5
ambari-web/app/controllers/wizard/step8_controller.js

@@ -802,7 +802,6 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
 
 /**
    * Set displayed MetricsSink DB value based on DB type
-   * @param {Ember.Object} dbComponent
    * @method loadSinkDbValue
    */
   loadSinkDbValue: function () {
@@ -821,8 +820,7 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
   },
 
   /**
-   * Set dispalyed Hive DB value based on DB type
-   * @param {Ember.Object} dbComponent
+   * Set displayed Hive DB value based on DB type
    * @method loadHiveDbValue
    */
   loadHiveDbValue: function () {
@@ -896,7 +894,6 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
 
   /**
    * Set displayed Oozie DB value based on DB type
-   * @param {Object} dbComponent
    * @method loadOozieDbValue
    */
   loadOozieDbValue: function () {
@@ -938,7 +935,6 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
 
   /**
    * Set displayed Nagion Admin value
-   * @param {Object} nagiosAdmin
    * @method loadNagiosAdminValue
    */
   loadNagiosAdminValue: function () {
@@ -1500,6 +1496,7 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
     }
     return isChanged;
   },
+
   /**
    * Create config objects for cluster and services
    * @method createConfigurations
@@ -1544,6 +1541,7 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
         }
       }, this);
     }, this);
+    this.createNotification();
   },
 
   /**
@@ -1688,6 +1686,7 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
 
   /**
    * proxyuser configs which depend on service
+   * @type {{serviceName: string, user: string}[]}
    */
   optionalCoreSiteConfigs: [
     {
@@ -1821,5 +1820,55 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
       }
     }, this);
     return {type: 'storm-site', tag: tag, properties: stormProperties};
+  },
+
+  /**
+   * Create one Alert Notification (if user select this on step7)
+   * Only for Install Wizard!
+   * @method createNotification
+   */
+  createNotification: function () {
+    if (this.get('content.controllerName') !== 'installerController') return;
+    var miscConfigs = this.get('configs').filterProperty('serviceName', 'MISC'),
+      createNotification = miscConfigs.findProperty('name', 'create_notification').value;
+    if (createNotification === 'yes') {
+      var properties = {},
+        names = [
+          'ambari.dispatch.recipients',
+          'mail.smtp.host',
+          'mail.smtp.port',
+          'mail.smtp.from',
+          'mail.smtp.starttls.enable',
+          'mail.smtp.startssl.enable'
+        ];
+      if (miscConfigs.findProperty('name', 'smtp_use_auth').value == 'true') { // yes, it's not converted to boolean
+        names.pushObjects(['ambari.dispatch.credential.username', 'ambari.dispatch.credential.password']);
+      }
+      var customConfigNames = miscConfigs.filterProperty('displayType', 'advanced').filterProperty('filename', '').mapProperty('name');
+      if (customConfigNames) {
+        names.pushObjects(customConfigNames);
+      }
+      names.forEach(function (name) {
+        properties[name] = miscConfigs.findProperty('name', name).value;
+      });
+
+      //properties['mail.smtp.starttls.enable'] = miscConfigs.findProperty('').value;
+      var apiObject = {
+        AlertTarget: {
+          name: 'Initial Notification',
+          description: 'Notification created during cluster installing',
+          global: true,
+          notification_type: 'EMAIL',
+          alert_states: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'],
+          properties: properties
+        }
+      };
+      this.addRequestToAjaxQueue({
+        name: 'alerts.create_alert_notification',
+        data: {
+          data: apiObject
+        }
+      });
+    }
   }
 });

+ 126 - 0
ambari-web/app/data/HDP2/site_properties.js

@@ -4437,6 +4437,132 @@ module.exports =
       "serviceName": "MISC",
       "filename": "cluster-env.xml",
       "category": "Users and Groups"
+    },
+    {
+      "id": "puppet var",
+      "name": "create_notification",
+      "displayName": "Create Notification",
+      "isRequired": true,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": false,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "defaultValue": "no"
+    },
+    {
+      "id": "puppet var",
+      "name": "mail.smtp.host",
+      "displayName": "SMTP Host",
+      "displayType": "host",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
+    },
+    {
+      "id": "puppet var",
+      "name": "mail.smtp.port",
+      "displayName": "SMTP Port",
+      "displayType": "int",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
+    },
+    {
+      "id": "puppet var",
+      "name": "mail.smtp.from",
+      "displayName": "FROM Email Address",
+      "displayType": "email",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
+    },
+    {
+      "id": "puppet var",
+      "name": "ambari.dispatch.recipients",
+      "displayName": " TO Email Address",
+      "displayType": "email",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
+    },
+    {
+      "id": "puppet var",
+      "name": "smtp_use_auth",
+      "displayName": "SMTP server requires authentication",
+      "displayType": "checkbox",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "defaultValue": true,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
+    },
+    {
+      "id": "puppet var",
+      "name": "ambari.dispatch.credential.username",
+      "displayName": "SMTP Username",
+      "displayType": "string",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-2"
+    },
+    {
+      "id": "puppet var",
+      "name": "ambari.dispatch.credential.password",
+      "displayName": "SMTP Password",
+      "displayType": "string",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": true,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-2"
+    },
+    {
+      "id": "puppet var",
+      "name": "mail.smtp.starttls.enable",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": false,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
+    },
+    {
+      "id": "puppet var",
+      "name": "mail.smtp.startssl.enable",
+      "isRequired": false,
+      "isReconfigurable": true,
+      "isOverridable": false,
+      "isVisible": false,
+      "serviceName": "MISC",
+      "category": "Notifications",
+      "rowStyleClass": "indent-1"
     }
   ]
 };

+ 3 - 2
ambari-web/app/data/service_configs.js

@@ -21,7 +21,7 @@ require('models/service_config');
 
 /**
  * This
- * @type {Array} Array of non-service tabs that will appears on  Customizes services page
+ * @type {Array} Array of non-service tabs that will appears on Customizes services page
  */
 module.exports = [
   Em.Object.create({
@@ -29,7 +29,8 @@ module.exports = [
     displayName: 'Misc',
     configCategories: [
       App.ServiceConfigCategory.create({ name: 'General', displayName : 'General'}),
-      App.ServiceConfigCategory.create({ name: 'Users and Groups', displayName : 'Users and Groups'})
+      App.ServiceConfigCategory.create({ name: 'Users and Groups', displayName : 'Users and Groups'}),
+      App.ServiceConfigCategory.create({ name: 'Notifications', displayName : 'Notifications', isCustomView: true, customView: App.NotificationsConfigsView})
     ],
     configTypes: {
       "cluster-env": {supports: {final: false}}

+ 5 - 0
ambari-web/app/messages.js

@@ -695,6 +695,11 @@ Em.I18n.translations = {
   'installer.step7.oozie.database.new': 'New Derby Database',
   'installer.step7.hive.database.new.mysql': 'New MySQL Database',
   'installer.step7.hive.database.new.postgres': 'New PostgreSQL Database',
+  'installer.step7.misc.notification.configure':'Configure email notifications',
+  'installer.step7.misc.notification.configure.later':'Configure email notifications later',
+  'installer.step7.misc.notification.use_tls':'Use TLS',
+  'installer.step7.misc.notification.use_ssl':'Use SSL',
+
 
   'installer.step8.header':'Review',
   'installer.step8.body':'Please review the configuration before installation',

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

@@ -141,7 +141,7 @@ App.Group = Ember.Object.extend({
 });
 
 
-App.ServiceConfigProperty = Ember.Object.extend({
+App.ServiceConfigProperty = Em.Object.extend({
 
   id: '', //either 'puppet var' or 'site property'
   name: '',
@@ -195,6 +195,7 @@ App.ServiceConfigProperty = Ember.Object.extend({
   isNotSaved: false, // user property was added but not saved
   hasInitialValue: false, //if true then property value is defined and saved to server
   isHiddenByFilter: false, //if true then hide this property (filtered out)
+  rowStyleClass: null, // CSS-Class to be applied on the row showing this config
   /**
    * Usage example see on <code>App.ServiceConfigRadioButtons.handleDBConnectionProperty()</code>
    *

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

@@ -1108,6 +1108,12 @@ h1 {
         }
       }
     }
+    .entry-row.indent-1 {
+      margin: 10px 0px 10px 2em !important;
+    }
+    .entry-row.indent-2 {
+      margin: 10px 0px 10px 4em !important;
+    }
     .entry-row {
       margin: 10px 0;
       .control-label-span{
@@ -1126,6 +1132,10 @@ h1 {
         font-size: 13px;
         white-space: nowrap;
       }
+      input[type="radio"] {
+        margin-bottom: 3px !important;
+        margin-right: 5px !important;
+      }
       .control-group {
         margin: 0px;
         .overrideField {

+ 73 - 0
ambari-web/app/templates/common/configs/notifications_configs.hbs

@@ -0,0 +1,73 @@
+{{!
+* 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="accordion-heading" {{action "onToggleBlock" category target="view"}}>
+  <i {{bindAttr class=":pull-left :accordion-toggle view.category.isCollapsed:icon-caret-right:icon-caret-down"}}></i>
+  <a class="accordion-toggle">{{view.category.displayName}}</a>
+</div>
+
+<div class="accordion-body collapse in" {{bindAttr style="view.isCategoryBodyVisible"}}>
+  <div class="accordion-inner service-config-section">
+    <form class="form-horizontal" autocomplete="off">
+
+      <div class="entry-row">
+        {{view Ember.RadioButton name="createNotification" selectionBinding="view.createNotification" value="no"}} {{t installer.step7.misc.notification.configure.later}}
+      </div>
+
+      <div class="entry-row">
+        {{view Ember.RadioButton name="createNotification" selectionBinding="view.createNotification" value="yes"}} {{t installer.step7.misc.notification.configure}}
+      </div>
+
+      {{#each view.categoryConfigs}}
+        <div {{bindAttr class=":entry-row rowStyleClass isUserProperty:indent-1"}}>
+          <span {{bindAttr class="errorMessage:error: :control-group :control-label-span"}}>
+            <label class="control-label">
+              {{formatWordBreak displayName}}
+            </label>
+          </span>
+
+          <div {{bindAttr class="showLabel:controls"}}>
+            <div {{bindAttr class="errorMessage:error: warnMessage:warning: :control-group"}}>
+              {{view viewClass serviceConfigBinding="this" categoryConfigsAllBinding="view.categoryConfigsAll" }}
+              <span class="help-inline">{{errorMessage}}</span>
+              <span class="help-inline">{{warnMessage}}</span>
+            </div>
+          </div>
+        </div>
+      {{/each}}
+
+      <div class="entry-row indent-1">
+        {{view Ember.RadioButton name="tlsOrSsl" disabledBinding="view.configsAreDisabled" selectionBinding="view.tlsOrSsl" value="tls"}} {{t installer.step7.misc.notification.use_tls}}
+      </div>
+
+      <div class="entry-row indent-1">
+        {{view Ember.RadioButton name="tlsOrSsl" disabledBinding="view.configsAreDisabled" selectionBinding="view.tlsOrSsl" value="ssl"}} {{t installer.step7.misc.notification.use_ssl}}
+      </div>
+      
+      {{#isAccessible ADMIN}}
+        {{#if view.canEdit}}
+          {{#unless view.configsAreDisabled}}
+            <div class="entry-row indent-1">
+             <a href="#" {{action "showAddPropertyWindow" this target="view" }} >{{t installer.step7.config.addProperty}}...</a>
+            </div>
+          {{/unless}}
+        {{/if}}
+      {{/isAccessible}}
+    </form>
+  </div>
+</div>

+ 54 - 51
ambari-web/app/templates/common/configs/service_config.hbs

@@ -18,63 +18,64 @@
 
 {{#if view.supportsHostOverrides}}
   {{#if selectedService.restartRequired}}
-	<div class="alert">
-	  <div class="clearfix like_pointer collapsable" {{action toggleRestartMessageView target="view"}}>
-	      {{#if view.isRestartMessageCollapsed}}
-	        <i class="icon-caret-down pull-left"></i>
-	      {{else}}
-	        <i class="icon-caret-right pull-left"></i>
-	      {{/if}}
-	      <i class="icon-refresh"></i>
-	      <strong>{{t dashboard.services.configs.popup.restartService.header}}</strong> {{selectedService.restartRequiredMessage}}
-	  </div>
-	  <div class="service-body">
-	    <ul>
-	    {{#each host in selectedService.restartRequiredHostsAndComponents}}
-	      <li>
-	        <a href="#" {{action showDetails host.hostData}}>{{host.hostData.publicHostName}}</a>
-	        <ul>
-	          {{#each component in host.components}}
-	            <li>{{component.name}}</li>
-	          {{/each}}
-	        </ul>
-	      </li>
-	    {{/each}}
-	    </ul>
-	  </div>
-	</div>
-	{{/if}}
+    <div class="alert">
+      <div class="clearfix like_pointer collapsable" {{action toggleRestartMessageView target="view"}}>
+        {{#if view.isRestartMessageCollapsed}}
+          <i class="icon-caret-down pull-left"></i>
+        {{else}}
+          <i class="icon-caret-right pull-left"></i>
+        {{/if}}
+        <i class="icon-refresh"></i>
+        <strong>{{t dashboard.services.configs.popup.restartService.header}}</strong> {{selectedService.restartRequiredMessage}}
+      </div>
+      <div class="service-body">
+        <ul>
+          {{#each host in selectedService.restartRequiredHostsAndComponents}}
+            <li>
+              <a href="#" {{action showDetails host.hostData}}>{{host.hostData.publicHostName}}</a>
+              <ul>
+                {{#each component in host.components}}
+                  <li>{{component.name}}</li>
+                {{/each}}
+              </ul>
+            </li>
+          {{/each}}
+        </ul>
+      </div>
+    </div>
+  {{/if}}
 {{/if}}
 {{#if view.supportsHostOverrides}}
-	<div class="alert alert-info">
-	  {{t common.group}}&nbsp; 
+  <div class="alert alert-info">
+    {{t common.group}}&nbsp;
 	  <span class="btn-group">
-		  <button {{bindAttr disabled="controller.isHostsConfigsPage"}} class="btn dropdown-toggle" data-toggle="dropdown">{{selectedConfigGroup.displayNameHosts}}</button>
+		  <button {{bindAttr disabled="controller.isHostsConfigsPage"}} class="btn dropdown-toggle"
+                                                                    data-toggle="dropdown">{{selectedConfigGroup.displayNameHosts}}</button>
 		  <button {{bindAttr disabled="controller.isHostsConfigsPage"}} class="btn dropdown-toggle" data-toggle="dropdown">
-		    <span class="caret"></span>
-		  </button>
+        <span class="caret"></span>
+      </button>
 		  <ul class="dropdown-menu">
-		    <!-- available config group menu links -->
-		    {{#each configGroup in configGroups}}
-           <li>
-             <a href="#" {{action "selectConfigGroup" configGroup target="controller"}}>
-               {{configGroup.displayNameHosts}}
-             </a>
-           </li>
+        <!-- available config group menu links -->
+        {{#each configGroup in configGroups}}
+          <li>
+            <a href="#" {{action "selectConfigGroup" configGroup target="controller"}}>
+              {{configGroup.displayNameHosts}}
+            </a>
+          </li>
         {{/each}}
-		  </ul>
+      </ul>
 		</span>
     {{#isAccessible ADMIN}}
       {{#if controller.isHostsConfigsPage}}
-          &nbsp;<a href="#" {{action "switchHostGroup" target="controller"}}>{{t common.change}}</a>
+        &nbsp;<a href="#" {{action "switchHostGroup" target="controller"}}>{{t common.change}}</a>
       {{else}}
-          <a href="#"  class="link-left-pad" {{action "manageConfigurationGroup" target="controller"}}>{{t services.service.actions.manage_configuration_groups.short}}</a>
+        <a href="#" class="link-left-pad" {{action "manageConfigurationGroup" target="controller"}}>{{t services.service.actions.manage_configuration_groups.short}}</a>
       {{/if}}
     {{/isAccessible}}
-     <div class="pull-right">
-       {{view App.FilterComboCleanableView filterBinding="view.filter" columnsBinding="view.columns" popoverDescriptionBinding="view.propertyFilterPopover"}}
-     </div>
-	</div>
+    <div class="pull-right">
+      {{view App.FilterComboCleanableView filterBinding="view.filter" columnsBinding="view.columns" popoverDescriptionBinding="view.propertyFilterPopover"}}
+    </div>
+  </div>
 {{/if}}
 
 {{#if view.showConfigHistoryFeature}}
@@ -82,13 +83,15 @@
 {{/if}}
 
 {{#if versionLoaded}}
+  {{#each category in selectedService.configCategories}}
     <div class="accordion">
-      {{#each category in selectedService.configCategories}}
-        {{#unless category.isCustomView}}
-          {{view App.ServiceConfigsByCategoryView categoryBinding="category" canEditBinding="view.canEdit" serviceBinding="selectedService" serviceConfigsBinding="selectedService.configs" supportsHostOverridesBinding="view.supportsHostOverrides"}}
-        {{/unless}}
-      {{/each}}
+      {{#if category.isCustomView}}
+        {{view category.customView categoryBinding="category" serviceBinding="selectedService" canEditBinding="view.canEdit" serviceConfigsBinding="selectedService.configs"}}
+      {{else}}
+        {{view App.ServiceConfigsByCategoryView categoryBinding="category" canEditBinding="view.canEdit" serviceBinding="selectedService" serviceConfigsBinding="selectedService.configs" supportsHostOverridesBinding="view.supportsHostOverrides"}}
+      {{/if}}
     </div>
+  {{/each}}
 {{else}}
-    <div class="spinner"></div>
+  <div class="spinner"></div>
 {{/if}}

+ 1 - 1
ambari-web/app/utils/config.js

@@ -974,7 +974,7 @@ App.config = Em.Object.create({
   },
   
   /**
-   * Add aditional properties to advanced property config object.
+   * Add additional properties to advanced property config object.
    * Additional logic based on `property_type`.
    *
    * @method advancedConfigIdentityData

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

@@ -36,6 +36,7 @@ require('views/common/configs/services_config');
 require('views/common/configs/overriddenProperty_view');
 require('views/common/configs/compare_property_view');
 require('views/common/configs/config_history_flow');
+require('views/common/configs/custom_category_views/notification_configs_view');
 require('views/common/filter_combobox');
 require('views/common/filter_combo_cleanable');
 require('views/common/table_view');

+ 132 - 0
ambari-web/app/views/common/configs/custom_category_views/notification_configs_view.js

@@ -0,0 +1,132 @@
+/**
+ * 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');
+
+/**
+ * Custom view for Notification section for MISC tab
+ * Used only in the Install Wizard
+ * Show configs for creating Init Notification (@see 'data/HDP2/site_properties' for list of the configs used here)
+ *
+ * @type {App.NotificationsConfigsView}
+ */
+App.NotificationsConfigsView = App.ServiceConfigsByCategoryView.extend({
+
+  templateName: require('templates/common/configs/notifications_configs'),
+
+  /**
+   * @type {string} "yes|no"
+   */
+  createNotification: 'no',
+
+  /**
+   * @type {string} "tls|ssl"
+   */
+  tlsOrSsl: 'tls',
+
+  /**
+   * Determines if notification configs should be disabled
+   * @type {boolean}
+   */
+  configsAreDisabled: true,
+
+  /**
+   * Config with flag for user auth in the notification
+   * @type {App.ServiceConfigProperty}
+   */
+  useAuthConfig: function () {
+    return this.get('categoryConfigs').findProperty('name', 'smtp_use_auth');
+  }.property(),
+
+  willInsertElement: function () {
+    this._super();
+    this.set('createNotification', this.get('categoryConfigsAll').findProperty('name', 'create_notification').get('value'));
+    this.set('tlsOrSsl', this.get('categoryConfigsAll').findProperty('name', 'mail.smtp.starttls.enable').get('value') ? 'tls' : 'ssl');
+    var smtp_use_auth = this.get('categoryConfigsAll').findProperty('name', 'smtp_use_auth');
+    var v = (smtp_use_auth.get('value') == 'true');
+    smtp_use_auth.set('value', v);
+    this.updateCategoryConfigs();
+  },
+
+  /**
+   * If <code>tlsOrSsl</code> was changed two configs should be updated
+   * TLS and SSL can't be enabled in the same time
+   * @method onTlsOrSslChanged
+   */
+  onTlsOrSslChanged: function () {
+    var tlsOrSsl = this.get('tlsOrSsl');
+    this.get('categoryConfigsAll').findProperty('name', 'mail.smtp.starttls.enable').set('value', tlsOrSsl == 'tls');
+    this.get('categoryConfigsAll').findProperty('name', 'mail.smtp.startssl.enable').set('value', tlsOrSsl == 'ssl');
+  }.observes('tlsOrSsl'),
+
+  /**
+   * Update username and password fields state according to <code>useAuthConfig.value</code>
+   * @method onUseAuthConfigChange
+   */
+  onUseAuthConfigChange: function () {
+    var configsToUpdate = ['ambari.dispatch.credential.username', 'ambari.dispatch.credential.password'],
+      useAuthConfigValue = this.get('useAuthConfig.value'),
+      useAuthConfigIsEditable = this.get('useAuthConfig.isEditable'),
+      self = this;
+    this.get('categoryConfigs').forEach(function (config) {
+      if (configsToUpdate.contains(config.get('name'))) {
+        var flag = useAuthConfigIsEditable ? useAuthConfigValue : false;
+        self.updateConfig(config, flag);
+      }
+    });
+  }.observes('useAuthConfig.value'),
+
+  /**
+   * Update all notification fields state according to <code>createNotification</code>
+   * If user select to create notification, all fields become editable and required (also run validation for each)
+   * If user select don't create notification, all fields become disabled, not required and valid
+   * @method updateCategoryConfigs
+   */
+  updateCategoryConfigs: function () {
+    var createNotification = this.get('createNotification'),
+      self = this;
+    this.get('categoryConfigs').forEach(function (config) {
+      var flag = (createNotification == 'yes');
+      self.updateConfig(config, flag);
+    });
+    this.set('configsAreDisabled', this.get('createNotification') == 'no');
+    this.onUseAuthConfigChange();
+    this.get('categoryConfigsAll').findProperty('name', 'create_notification').set('value', createNotification);
+  }.observes('createNotification'),
+
+  /**
+   * According to <code>flag</code>, enable/disable <code>config</code>
+   * If <code>flag</code> is true - validate <code>config</code> value
+   * If <code>flag</code> is false - mark <code>config</code> as valid
+   * @param {App.ServiceConfigProperty} config
+   * @param {boolean} flag
+   * @method updateConfig
+   */
+  updateConfig: function (config, flag) {
+    config.set('isRequired', flag);
+    config.set('isEditable', flag);
+    if (flag) {
+      config.validate();
+    }
+    else {
+      config.set('errorMessage', '');
+      config.propertyDidChange('isValid');
+    }
+  }
+
+});

+ 3 - 4
ambari-web/app/views/common/configs/services_config.js

@@ -86,7 +86,6 @@ App.ServiceConfigView = Em.View.extend({
   )
 });
 
-
 App.ServiceConfigsByCategoryView = Ember.View.extend(App.UserPref, {
 
   templateName: require('templates/common/configs/service_config_category'),
@@ -527,7 +526,7 @@ App.ServiceConfigsByCategoryView = Ember.View.extend(App.UserPref, {
         return !!matchingConfigType;
       }
 
-      var supportsFinal = shouldSupportFinal(siteFileName);
+      var supportsFinal = siteFileName ? shouldSupportFinal(siteFileName) : false;
 
       function isDuplicatedConfigKey(name) {
         return siteFileProperties.findProperty('name', name) || configsOfFile.findProperty('name', name);
@@ -802,7 +801,7 @@ App.ServiceConfigContainerView = Em.ContainerView.extend({
       }
       var categoriesToPush = [];
       this.get('controller.selectedService.configCategories').forEach(function (item) {
-        var categoryView = item.get('isCustomView') ?  null : App.ServiceConfigsByCategoryView;
+        var categoryView = item.get('isCustomView') ? item.get('customView') : App.ServiceConfigsByCategoryView;
         if (categoryView !== null) {
           categoriesToPush.pushObject(categoryView.extend({
             category: item,
@@ -851,4 +850,4 @@ App.ServiceConfigTab = Ember.View.extend({
     var serviceName = this.get('controller.selectedService.serviceName');
     this.$('a[href="#' + serviceName + '"]').tab('show');
   }
-});
+});