You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ao...@apache.org on 2017/12/07 14:02:38 UTC

[01/50] [abbrv] ambari git commit: AMBARI-22495. Installer - Select Version page should show HDP-GPL repo if necessary (vsubramanian)

Repository: ambari
Updated Branches:
  refs/heads/branch-3.0-perf eaf1fd5ce -> 366f6ca9b


AMBARI-22495. Installer - Select Version page should show HDP-GPL repo if necessary (vsubramanian)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6b17d014
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6b17d014
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6b17d014

Branch: refs/heads/branch-3.0-perf
Commit: 6b17d0142266f714807bd06e3ce1afbe535a0a73
Parents: 9fc7223
Author: Vivek Ratnavel Subramanian <vi...@gmail.com>
Authored: Wed Nov 22 18:00:32 2017 -0800
Committer: Vivek Ratnavel Subramanian <vi...@gmail.com>
Committed: Wed Nov 22 18:00:32 2017 -0800

----------------------------------------------------------------------
 ambari-web/app/controllers/installer.js         | 53 +++++++++++---------
 .../app/controllers/wizard/step8_controller.js  | 12 +++--
 .../app/mappers/repository_version_mapper.js    |  3 +-
 ambari-web/app/mappers/stack_mapper.js          |  3 +-
 ambari-web/app/models/repository.js             | 17 +++++++
 .../app/models/stack_version/repository.js      |  3 +-
 ambari-web/app/templates/wizard/step1.hbs       | 36 +++++++++++++
 ambari-web/test/controllers/installer_test.js   | 14 ++++--
 8 files changed, 103 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/controllers/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js
index 3c50b26..d6be78d 100644
--- a/ambari-web/app/controllers/installer.js
+++ b/ambari-web/app/controllers/installer.js
@@ -813,6 +813,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
             "repo_id": repository.get('repoId'),
             "repo_name": repository.get('repoName'),
             "components": repository.get('components'),
+            "tags": repository.get('tags'),
             "distribution": repository.get('distribution')
           }
         });
@@ -833,7 +834,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
     var dfd = $.Deferred();
     if (selectedStack && selectedStack.get('operatingSystems')) {
       this.set('validationCnt', selectedStack.get('operatingSystems').filterProperty('isSelected').filterProperty('isEmpty', false).map(function (os) {
-        return os.get('repositories.length');
+        return os.get('repositories').filterProperty('showRepo', true).length;
       }).reduce(Em.sum, 0));
       var verifyBaseUrl = !wizardStep1Controller.get('skipValidationChecked') && !wizardStep1Controller.get('selectedStack.useRedhatSatellite');
       if (!verifyBaseUrl) {
@@ -842,32 +843,34 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
       selectedStack.get('operatingSystems').forEach(function (os) {
         if (os.get('isSelected') && !os.get('isEmpty')) {
           os.get('repositories').forEach(function (repo) {
-            repo.setProperties({
-              errorTitle: '',
-              errorContent: '',
-              validation: 'INPROGRESS'
-            });
-            this.set('content.isCheckInProgress', true);
-            App.ajax.send({
-              name: 'wizard.advanced_repositories.valid_url',
-              sender: this,
-              data: {
-                stackName: stackName,
-                stackVersion: stackVersion,
-                repoId: repo.get('repoId'),
-                osType: os.get('osType'),
-                osId: os.get('id'),
-                dfd: dfd,
+            if (repo.get('showRepo')) {
+              repo.setProperties({
+                errorTitle: '',
+                errorContent: '',
+                validation: 'INPROGRESS'
+              });
+              this.set('content.isCheckInProgress', true);
+              App.ajax.send({
+                name: 'wizard.advanced_repositories.valid_url',
+                sender: this,
                 data: {
-                  'Repositories': {
-                    'base_url': repo.get('baseUrl'),
-                    "verify_base_url": verifyBaseUrl
+                  stackName: stackName,
+                  stackVersion: stackVersion,
+                  repoId: repo.get('repoId'),
+                  osType: os.get('osType'),
+                  osId: os.get('id'),
+                  dfd: dfd,
+                  data: {
+                    'Repositories': {
+                      'base_url': repo.get('baseUrl'),
+                      "verify_base_url": verifyBaseUrl
+                    }
                   }
-                }
-              },
-              success: 'checkRepoURLSuccessCallback',
-              error: 'checkRepoURLErrorCallback'
-            });
+                },
+                success: 'checkRepoURLSuccessCallback',
+                error: 'checkRepoURLErrorCallback'
+              });
+            }
           }, this);
         } else if (os.get('isSelected') && os.get('isEmpty')) {
           os.set('isSelected', false);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/controllers/wizard/step8_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step8_controller.js b/ambari-web/app/controllers/wizard/step8_controller.js
index 94139e0..e64a09a 100644
--- a/ambari-web/app/controllers/wizard/step8_controller.js
+++ b/ambari-web/app/controllers/wizard/step8_controller.js
@@ -307,11 +307,13 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz
         selectedStack.get('operatingSystems').forEach(function (os) {
           if (os.get('isSelected')) {
             os.get('repositories').forEach(function(repo) {
-              allRepos.push(Em.Object.create({
-                base_url: repo.get('baseUrl'),
-                os_type: repo.get('osType'),
-                repo_id: repo.get('repoId')
-              }));
+              if (repo.get('showRepo')) {
+                allRepos.push(Em.Object.create({
+                  base_url: repo.get('baseUrl'),
+                  os_type: repo.get('osType'),
+                  repo_id: repo.get('repoId')
+                }));
+              }
             }, this);
           }
         }, this);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/mappers/repository_version_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/repository_version_mapper.js b/ambari-web/app/mappers/repository_version_mapper.js
index 3838d34..8843dcd 100644
--- a/ambari-web/app/mappers/repository_version_mapper.js
+++ b/ambari-web/app/mappers/repository_version_mapper.js
@@ -73,7 +73,8 @@ App.repoVersionMapper = App.QuickDataMapper.create({
     repo_id : 'Repositories.repo_id',
     repo_name : 'Repositories.repo_name',
     stack_name : 'Repositories.stack_name',
-    stack_version : 'Repositories.stack_version'
+    stack_version : 'Repositories.stack_version',
+    tags: 'Repositories.tags'
   },
 
   map: function (json, loadAll, isCurrentStackOnly) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/mappers/stack_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/stack_mapper.js b/ambari-web/app/mappers/stack_mapper.js
index 07fb137..323a033 100644
--- a/ambari-web/app/mappers/stack_mapper.js
+++ b/ambari-web/app/mappers/stack_mapper.js
@@ -87,7 +87,8 @@ App.stackMapper = App.QuickDataMapper.create({
     stack_version: 'stack_version',
     operating_system_id: 'os_id',
     components: 'components',
-    distribution: 'distribution'
+    distribution: 'distribution',
+    tags: 'tags'
   },
   
   map: function(json) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/models/repository.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/repository.js b/ambari-web/app/models/repository.js
index c50750f..d85c55d 100644
--- a/ambari-web/app/models/repository.js
+++ b/ambari-web/app/models/repository.js
@@ -34,6 +34,7 @@ App.Repository = DS.Model.extend({
   operatingSystem: DS.belongsTo('App.OperatingSystem'),
   components: DS.attr('string'),
   distribution: DS.attr('string'),
+  tags: DS.attr('array'),
 
   validation: DS.attr('string', {defaultValue: ''}),
   validationClassName: Em.computed.getByKey('validationClassNameMap', 'validation', ''),
@@ -66,6 +67,22 @@ App.Repository = DS.Model.extend({
     return this.get('repoName').contains('UTILS');
   }.property('repoName'),
 
+  /**
+   * @type {boolean}
+   */
+  isGPL: function () {
+    return this.get('tags').contains('GPL');    
+  }.property('tags'),
+
+  /**
+   * Determines whether a repo needs to be displayed in the UI or not
+   * @type {boolean}
+   */
+  showRepo: function () {
+    const isGPLAccepted = App.router.get('clusterController.ambariProperties')['gpl.license.accepted'] === 'true';
+    return isGPLAccepted || !this.get('isGPL');
+  }.property('isGPL'),
+
   undo: Em.computed.notEqualProperties('baseUrl', 'baseUrlInit'),
 
   notEmpty: Em.computed.notEqual('baseUrl', ''),

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/models/stack_version/repository.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/stack_version/repository.js b/ambari-web/app/models/stack_version/repository.js
index 8bd4323..6c93416 100644
--- a/ambari-web/app/models/stack_version/repository.js
+++ b/ambari-web/app/models/stack_version/repository.js
@@ -29,7 +29,8 @@ App.Repository = DS.Model.extend({
   repoName : DS.attr('string'),
   stackName : DS.attr('string'),
   stackVersion : DS.attr('string'),
-  operatingSystem: DS.belongsTo('App.OS')
+  operatingSystem: DS.belongsTo('App.OS'),
+  tags: DS.attr('array')
 });
 
 App.Repository.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/app/templates/wizard/step1.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step1.hbs b/ambari-web/app/templates/wizard/step1.hbs
index 6b15e65..eb746c3 100644
--- a/ambari-web/app/templates/wizard/step1.hbs
+++ b/ambari-web/app/templates/wizard/step1.hbs
@@ -131,6 +131,42 @@
                       </div>
                       {{! Add OS END}}
                     </div>
+                    <div class="span9 repo-name-url">
+                      {{#each repository in operatingSystem.repositories}}
+                        {{#if repository.showRepo}}
+                        <div {{bindAttr class=":clearfix :repo-name-url-inner repository.repoName"}}>
+                          <div class="span3">
+                            <label class="repo-name-label control-label">{{repository.repoId}}</label>
+                          </div>
+                          <div class="validation-td span1">
+                            {{#if repository.validation}}
+                              {{view view.popoverView repositoryBinding="repository"}}
+                            {{/if}}
+                          </div>
+                          <div {{bindAttr class=":span8 :repo-url repository.invalidFormatError:textfield-error repository.invalidError:textfield-error"}}>
+                            {{view Ember.TextField placeholderBinding="repository.placeholder" valueBinding="repository.baseUrl" disabledBinding="controller.selectedStack.useRedhatSatellite"}}
+                            {{#if controller.selectedStack.usePublicRepo}}
+                              {{#if repository.undo}}
+                                <i class="icon-undo" data-toggle="tooltip"
+                                  {{action "doRestoreDefaultValue" repository target="controller"}}
+                                  {{translateAttr title="common.undo"}}>
+                                </i>
+                              {{/if}}
+                            {{else}}
+                              {{#if repository.notEmpty}}
+                                <i class="icon-undo" data-toggle="tooltip"
+                                  {{action "doRestoreToEmpty" repository target="controller"}}
+                                  {{translateAttr title="common.undo"}}>
+                                </i>
+                              {{/if}}
+                            {{/if}}
+                          </div>
+                        </div>
+                        {{/if}}
+                      {{/each}}
+                    </div>
+                    <div {{bindAttr class=":span1 :remove-icon controller.selectedStack.useRedhatSatellite:disabled"}} {{action "removeOS" operatingSystem target="controller"}}>
+                      <i class="icon-minus"></i>{{t common.remove}}</div>
                   </div>
                 </div>
                 <table class="table table-hover">

http://git-wip-us.apache.org/repos/asf/ambari/blob/6b17d014/ambari-web/test/controllers/installer_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/installer_test.js b/ambari-web/test/controllers/installer_test.js
index 65a1e5c..3831c79 100644
--- a/ambari-web/test/controllers/installer_test.js
+++ b/ambari-web/test/controllers/installer_test.js
@@ -92,7 +92,8 @@ describe('App.InstallerController', function () {
                 isEmpty: false,
                 errorTitle: '1',
                 errorContent: '1',
-                validation: ''
+                validation: '',
+                showRepo: true
               })
             ])
           })
@@ -131,7 +132,8 @@ describe('App.InstallerController', function () {
                   "isEmpty": false,
                   "errorTitle": "",
                   "errorContent": "",
-                  "validation": "INPROGRESS"
+                  "validation": "INPROGRESS",
+                  "showRepo": true
                 }
               ]
             }
@@ -172,7 +174,8 @@ describe('App.InstallerController', function () {
                 isEmpty: false,
                 errorTitle: '1',
                 errorContent: '1',
-                validation: ''
+                validation: '',
+                showRepo: true
               })
             ])
           })
@@ -189,7 +192,7 @@ describe('App.InstallerController', function () {
         }
       }
     };
-    it ('Should check stacks for sucess', function() {
+    it ('Should check stacks for success', function() {
 
       installerController.set('content.stacks', stacks);
       installerController.checkRepoURLSuccessCallback(null,null,data);
@@ -220,7 +223,8 @@ describe('App.InstallerController', function () {
                   "isEmpty": false,
                   "errorTitle": "1",
                   "errorContent": "1",
-                  "validation": "OK"
+                  "validation": "OK",
+                  "showRepo": true
                 }
               ]
             }


[37/50] [abbrv] ambari git commit: AMBARI-22484. Stack advisor should disallow lzo enable without accepting license agreement. (mpapirkovskyy)

Posted by ao...@apache.org.
AMBARI-22484. Stack advisor should disallow lzo enable without accepting license agreement. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/41853a10
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/41853a10
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/41853a10

Branch: refs/heads/branch-3.0-perf
Commit: 41853a1041a848b69384592c49f8f5b539a5c4f9
Parents: 7750398
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Wed Nov 29 16:48:11 2017 +0200
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Wed Nov 29 18:30:08 2017 +0200

----------------------------------------------------------------------
 .../stackadvisor/StackAdvisorRequest.java       | 11 +++++
 .../commands/StackAdvisorCommand.java           |  2 +
 .../ambari/server/controller/AmbariServer.java  |  3 +-
 .../internal/StackAdvisorResourceProvider.java  |  9 +++-
 .../GPLLicenseNotAcceptedException.java         | 28 +++++++++++
 .../stacks/HDP/2.0.6/services/stack_advisor.py  | 17 +++++++
 .../ValidationResourceProviderTest.java         |  4 +-
 .../stacks/2.0.6/common/test_stack_advisor.py   | 51 ++++++++++++++++++--
 8 files changed, 116 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
index cd26c56..62b8d15 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
@@ -51,6 +51,7 @@ public class StackAdvisorRequest {
   private Set<RecommendationResponse.ConfigGroup> configGroups;
   private Map<String, String> userContext = new HashMap<>();
   private Map<String, Object> ldapConfig = new HashMap<>();
+  private Boolean gplLicenseAccepted;
 
   public String getStackName() {
     return stackName;
@@ -122,6 +123,10 @@ public class StackAdvisorRequest {
     this.configGroups = configGroups;
   }
 
+  public Boolean getGplLicenseAccepted() {
+    return gplLicenseAccepted;
+  }
+
   private StackAdvisorRequest(String stackName, String stackVersion) {
     this.stackName = stackName;
     this.stackVersion = stackVersion;
@@ -194,6 +199,12 @@ public class StackAdvisorRequest {
       return this;
     }
 
+    public StackAdvisorRequestBuilder withGPLLicenseAccepted(
+        Boolean gplLicenseAccepted) {
+      this.instance.gplLicenseAccepted = gplLicenseAccepted;
+      return this;
+    }
+
     public StackAdvisorRequestBuilder withLdapConfig(Map<String, Object> ldapConfig) {
       Preconditions.checkNotNull(ldapConfig);
       this.instance.ldapConfig = ldapConfig;

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
index 1b89c4f..4ec15ef 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
@@ -107,6 +107,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   private static final String CONFIGURATIONS_PROPERTY = "configurations";
   private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed-configurations";
   private static final String USER_CONTEXT_PROPERTY = "user-context";
+  private static final String GPL_LICENSE_ACCEPTED = "gpl-license-accepted";
   private static final String AMBARI_SERVER_CONFIGURATIONS_PROPERTY = "ambari-server-properties";
 
   private File recommendationsDir;
@@ -269,6 +270,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
     JsonNode userContext = mapper.valueToTree(request.getUserContext());
     root.put(USER_CONTEXT_PROPERTY, userContext);
+    root.put(GPL_LICENSE_ACCEPTED, request.getGplLicenseAccepted());
   }
 
   private void populateConfigGroups(ObjectNode root,

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 6ceed4a..863313b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -908,7 +908,8 @@ public class AmbariServer {
     PersistKeyValueService.init(injector.getInstance(PersistKeyValueImpl.class));
     KeyService.init(injector.getInstance(PersistKeyValueImpl.class));
     BootStrapResource.init(injector.getInstance(BootStrapImpl.class));
-    StackAdvisorResourceProvider.init(injector.getInstance(StackAdvisorHelper.class));
+    StackAdvisorResourceProvider.init(injector.getInstance(StackAdvisorHelper.class),
+        injector.getInstance(Configuration.class));
     StageUtils.setGson(injector.getInstance(Gson.class));
     StageUtils.setTopologyManager(injector.getInstance(TopologyManager.class));
     StageUtils.setConfiguration(injector.getInstance(Configuration.class));

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java
index 1ea664c..67c177e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java
@@ -36,6 +36,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestBuilder;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestType;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
+import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.Resource.Type;
@@ -82,12 +83,14 @@ public abstract class StackAdvisorResourceProvider extends ReadOnlyResourceProvi
   private static final String CONFIG_GROUPS_HOSTS_PROPERTY = "hosts";
 
   protected static StackAdvisorHelper saHelper;
+  protected static Configuration configuration;
   protected static final String USER_CONTEXT_OPERATION_PROPERTY = "user_context/operation";
   protected static final String USER_CONTEXT_OPERATION_DETAILS_PROPERTY = "user_context/operation_details";
 
   @Inject
-  public static void init(StackAdvisorHelper instance) {
+  public static void init(StackAdvisorHelper instance, Configuration serverConfig) {
     saHelper = instance;
+    configuration = serverConfig;
   }
 
   protected StackAdvisorResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
@@ -133,6 +136,7 @@ public abstract class StackAdvisorResourceProvider extends ReadOnlyResourceProvi
           hgHostsMap);
       Map<String, Map<String, Map<String, String>>> configurations = calculateConfigurations(request);
       Map<String, String> userContext = readUserContext(request);
+      Boolean gplLicenseAccepted = configuration.getGplLicenseAccepted();
 
       List<ChangedConfigInfo> changedConfigurations =
         requestType == StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES ?
@@ -147,7 +151,8 @@ public abstract class StackAdvisorResourceProvider extends ReadOnlyResourceProvi
         withConfigurations(configurations).
         withConfigGroups(configGroups).
         withChangedConfigurations(changedConfigurations).
-        withUserContext(userContext).build();
+        withUserContext(userContext).
+        withGPLLicenseAccepted(gplLicenseAccepted).build();
     } catch (Exception e) {
       LOG.warn("Error occurred during preparation of stack advisor request", e);
       Response response = Response.status(Status.BAD_REQUEST)

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/main/java/org/apache/ambari/server/topology/GPLLicenseNotAcceptedException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/GPLLicenseNotAcceptedException.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/GPLLicenseNotAcceptedException.java
new file mode 100644
index 0000000..b444d01
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/GPLLicenseNotAcceptedException.java
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+
+package org.apache.ambari.server.topology;
+
+/**
+ * Indicates an not permitted LZO usage.
+ */
+public class GPLLicenseNotAcceptedException extends Exception {
+  public GPLLicenseNotAcceptedException(String s) {
+    super(s);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
index a194332..bfa2f5a 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
@@ -351,6 +351,22 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     # recommendations for "hadoop.proxyuser.*.hosts", "hadoop.proxyuser.*.groups" properties in core-site
     self.recommendHadoopProxyUsers(configurations, services, hosts)
 
+  def getLZOSupportValidationItems(self, properties, services):
+    services_list = self.get_services_list(services)
+
+    if "HDFS" in services_list:
+      lzo_allowed = services["gpl-license-accepted"]
+      property_name = "io.compression.codec.lzo.class"
+      if property_name in properties:
+        property_value = properties.get(property_name)
+        if not lzo_allowed and "com.hadoop.compression.lzo.LzoCodec" in property_value:
+          return [{"config-name": property_name, "item": self.getErrorItem(
+            "Your Ambari Server has not been configured to download LZO and install it. "
+            "LZO is GPL software and requires you to accept a license prior to use. "
+            "Please refer to this documentation to configure Ambari before proceeding.")}]
+
+    return []
+
   def recommendHbaseConfigurations(self, configurations, clusterData, services, hosts):
     # recommendations for HBase env config
 
@@ -726,6 +742,7 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     validationItems = []
     validationItems.extend(self.getHadoopProxyUsersValidationItems(properties, services, hosts, configurations))
     validationItems.extend(self.getAmbariProxyUsersForHDFSValidationItems(properties, services))
+    validationItems.extend(self.getLZOSupportValidationItems(properties, services))
     return self.toConfigurationValidationProblems(validationItems, "core-site")
 
   def validatorOneDataDirPerPartition(self, properties, propertyName, services, hosts, clusterEnv):

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ValidationResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ValidationResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ValidationResourceProviderTest.java
index c639d1f..42d4770 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ValidationResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ValidationResourceProviderTest.java
@@ -33,6 +33,7 @@ import java.util.Set;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
+import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.RequestStatus;
@@ -53,13 +54,14 @@ public class ValidationResourceProviderTest {
     doReturn(stackAdvisorRequest).when(provider).prepareStackAdvisorRequest(request);
 
     StackAdvisorHelper saHelper = mock(StackAdvisorHelper.class);
+    Configuration configuration = mock(Configuration.class);
 
     ValidationResponse response = mock(ValidationResponse.class);
     Version version = mock(Version.class);
     doReturn(3).when(response).getId();
     doReturn(version).when(response).getVersion();
     doReturn(response).when(saHelper).validate(any(StackAdvisorRequest.class));
-    ValidationResourceProvider.init(saHelper);
+    ValidationResourceProvider.init(saHelper, configuration);
 
     RequestStatus status = provider.createResources(request);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/41853a10/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
index 38d6ecd..6c774af 100644
--- a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
@@ -2521,7 +2521,8 @@ class TestHDP206StackAdvisor(TestCase):
                   'hadoop.proxyuser.hdfs-user.hosts': '*',
                   'hadoop.proxyuser.hdfs-user.groups': '*',
                   'hadoop.proxyuser.yarn-user.hosts': 'host1,host2',
-                  'hadoop.proxyuser.yarn-user.groups': '*'}
+                  'hadoop.proxyuser.yarn-user.groups': '*',
+                  'io.compression.codec.lzo.class': 'com.hadoop.compression.lzo.LzoCodec'}
     services = {
       'services':  [
         { 'StackServices': {'service_name': 'HDFS'}},
@@ -2537,7 +2538,8 @@ class TestHDP206StackAdvisor(TestCase):
         }
       ],
       'ambari-server-properties': {'ambari-server.user': 'ambari-user'},
-      'configurations': configurations
+      'configurations': configurations,
+      "gpl-license-accepted": True
     }
     hosts = {
       'items' : [
@@ -2551,7 +2553,21 @@ class TestHDP206StackAdvisor(TestCase):
     res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, recommendedDefaults, configurations, services, hosts)
     self.assertEquals(res, res_expected)
 
-    # 2) fail: test filter function: two RESOURCE_MANAGERs, hadoop.proxyuser.yarn-user.hosts is expected to be set
+    # 2) fail: gpl is not allowed
+    services["gpl-license-accepted"] = False
+    res_expected = [{'config-type': 'core-site',
+                     'message': 'Your Ambari Server has not been configured to download LZO and install it. '
+                                'LZO is GPL software and requires you to accept a license prior to use. '
+                                'Please refer to this documentation to configure Ambari before proceeding.',
+                     'type': 'configuration',
+                     'config-name': 'io.compression.codec.lzo.class',
+                     'level': 'ERROR'}]
+
+    res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, {}, configurations, services, hosts)
+    self.assertEquals(res, res_expected)
+    services["gpl-license-accepted"] = True
+
+    # 3) fail: test filter function: two RESOURCE_MANAGERs, hadoop.proxyuser.yarn-user.hosts is expected to be set
     del properties['hadoop.proxyuser.yarn-user.hosts']
     res_expected = [{'config-name': 'hadoop.proxyuser.yarn-user.hosts',
                      'config-type': 'core-site',
@@ -2561,13 +2577,13 @@ class TestHDP206StackAdvisor(TestCase):
     res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, recommendedDefaults, configurations, services, hosts)
     self.assertEquals(res, res_expected)
 
-    # 3) ok: test filter function: only one RESOURCE_MANAGER
+    # 4) ok: test filter function: only one RESOURCE_MANAGER
     services['services'][1]['components'][0]['StackServiceComponents']['hostnames'] = ["host1"]
     res_expected = []
     res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, recommendedDefaults, configurations, services, hosts)
     self.assertEquals(res, res_expected)
 
-    # 4) fail: some proxyusers are empty or absent:
+    # 5) fail: some proxyusers are empty or absent:
     del properties['hadoop.proxyuser.ambari-user.hosts']
     properties['hadoop.proxyuser.hdfs-user.groups'] = ''
     res_expected = [{'config-name': 'hadoop.proxyuser.hdfs-user.groups',
@@ -2627,6 +2643,31 @@ class TestHDP206StackAdvisor(TestCase):
     res = self.stackAdvisor.getHadoopProxyUsers(services, hosts, configurations)
     self.assertEquals(res, res_expected)
 
+  # def test_validateHDFSConfigurationsCoreSite(self):
+  #
+  #   configurations = {}
+  #   services = {"gpl-license-accepted": True, "services": [{"StackServices": {"service_name": "HDFS"}}], 'ambari-server-properties': {'ambari-server.user': 'ambari-user'}}
+  #
+  #   # 1) ok: gpl is allowed
+  #   properties = {'io.compression.codec.lzo.class': 'com.hadoop.compression.lzo.LzoCodec'}
+  #   res_expected = []
+  #
+  #   res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, {}, configurations, services, '')
+  #   self.assertEquals(res, res_expected)
+  #
+  #   # 2) fail: gpl is not allowed
+  #   services["gpl-license-accepted"] = False
+  #   res_expected = [{'config-type': 'core-site',
+  #                    'message': 'Your Ambari Server has not been configured to download LZO and install it. '
+  #                               'LZO is GPL software and requires you to accept a license prior to use. '
+  #                               'Please refer to this documentation to configure Ambari before proceeding.',
+  #                    'type': 'configuration',
+  #                    'config-name': 'io.compression.codec.lzo.class',
+  #                    'level': 'ERROR'}]
+  #
+  #   res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, {}, configurations, services, '')
+  #   self.assertEquals(res, res_expected)
+
   def test_validateOneDataDirPerPartition(self):
     recommendedDefaults = {
       'dfs.datanode.du.reserved': '1024'


[07/50] [abbrv] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
new file mode 100644
index 0000000..abe1780
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
@@ -0,0 +1,178 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('UsersListCtrl',
+['$scope', 'User', '$modal', '$rootScope', 'UserConstants', '$translate', 'Cluster', 'View', 'ConfirmationModal', 'Settings',
+function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, View, ConfirmationModal, Settings) {
+  var $t = $translate.instant;
+  $scope.constants = {
+    admin: $t('users.ambariAdmin'),
+    users: $t('common.users').toLowerCase()
+  };
+  $scope.minRowsToShowPagination = Settings.minRowsToShowPagination;
+  $scope.isLoading = false;
+  $scope.users = [];
+  $scope.usersPerPage = 10;
+  $scope.currentPage = 1;
+  $scope.totalUsers = 0;
+  $scope.filters = {
+    name: '',
+    status: null,
+    type: null
+  };
+  $scope.maxVisiblePages = 20;
+  $scope.tableInfo = {
+    total: 0,
+    showed: 0
+  };
+  $scope.isNotEmptyFilter = true;
+
+  $scope.pageChanged = function() {
+    $scope.loadUsers();
+  };
+  $scope.usersPerPageChanges = function() {
+    $scope.resetPagination();
+  };
+
+  $scope.loadUsers = function(){
+    $scope.isLoading = true;
+    User.list({
+      currentPage: $scope.currentPage,
+      usersPerPage: $scope.usersPerPage,
+      searchString: $scope.filters.name,
+      user_type: $scope.filters.type.value,
+      active: $scope.filters.status.value
+    }).then(function(data) {
+      $scope.isLoading = false;
+      $scope.totalUsers = data.data.itemTotal;
+      $scope.users = data.data.items.map(User.makeUser);
+      $scope.tableInfo.showed = data.data.items.length;
+      $scope.tableInfo.total = data.data.itemTotal;
+    });
+  };
+
+  $scope.resetPagination = function() {
+    $scope.currentPage = 1;
+    $scope.loadUsers();
+  };
+
+  $scope.activeFilterOptions = [
+    {label: $t('common.all'), value: '*'},
+    {label: $t('users.active'), value: true},
+    {label: $t('users.inactive'), value:false}
+  ];
+  $scope.filters.status = $scope.activeFilterOptions[0];
+
+  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
+    .concat(Object.keys(UserConstants.TYPES).map(function(key) {
+      return {
+        label: $t(UserConstants.TYPES[key].LABEL_KEY),
+        value: UserConstants.TYPES[key].VALUE
+      };
+    }));
+
+  $scope.filters.type = $scope.typeFilterOptions[0];
+
+  $scope.clearFilters = function () {
+    $scope.filters.name = '';
+    $scope.filters.type = $scope.typeFilterOptions[0];
+    $scope.filters.status = $scope.activeFilterOptions[0];
+    $scope.resetPagination();
+  };
+
+  $scope.loadUsers();
+
+  $scope.$watch(
+    function (scope) {
+      return Boolean(scope.filters.name || (scope.filters.status && scope.filters.status.value !== '*')
+        || (scope.filters.type && scope.filters.type.value !== '*'));
+    },
+    function (newValue, oldValue, scope) {
+      scope.isNotEmptyFilter = newValue;
+    }
+  );
+
+  $rootScope.$watch(function(scope) {
+    return scope.LDAPSynced;
+  }, function(LDAPSynced) {
+    if(LDAPSynced === true){
+      $rootScope.LDAPSynced = false;
+      $scope.loadUsers();
+    }
+  });
+
+  $scope.createUser = function () {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/userManagement/modals/userCreate.html',
+      controller: 'UserCreateCtrl',
+      backdrop: 'static'
+    });
+
+    modalInstance.result.finally($scope.loadUsers);
+  };
+
+  $scope.deleteUser = function(user) {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.user')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.user').toLowerCase(),
+        instanceName: '"' + user.user_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : user.user_name,
+        typeFilter : {value: 'USER'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'USER') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        User.delete(user.user_name).then(function() {
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+          $scope.loadUsers();
+        });
+      });
+    });
+  };
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
deleted file mode 100644
index bcb7bfc..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersCreateCtrl.js
+++ /dev/null
@@ -1,75 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('UsersCreateCtrl',['$scope', '$routeParams', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', function($scope, $routeParams, User, $location, Alert, UnsavedDialog, $translate) {
-  var $t = $translate.instant;
-  $scope.user = {
-    active: true
-  };
-  var targetUrl = '/users';
-
-  $scope.createUser = function() {
-    $scope.form.submitted = true;
-    if ($scope.form.$valid){
-      User.create({
-        'Users/user_name': $scope.user.user_name,
-        'Users/password': $scope.user.password,
-        'Users/active': !!$scope.user.active,
-        'Users/admin': !!$scope.user.admin
-      }).then(function() {
-        Alert.success($t('users.alerts.userCreated', {
-          userName: $scope.user.user_name,
-          encUserName: encodeURIComponent($scope.user.user_name)
-        }));
-        $scope.form.$setPristine();
-        $location.path(targetUrl);
-      }).catch(function(data) {
-        Alert.error($t('users.alerts.userCreationError'), data.data.message);
-      });
-    }
-  };
-
-  $scope.cancel = function() {
-    $scope.form.$setPristine();
-    $location.path('/users');
-  };
-
-  $scope.$on('$locationChangeStart', function(event, __targetUrl) {
-        
-    if( $scope.form.$dirty ){
-      UnsavedDialog().then(function(action) {
-        targetUrl = __targetUrl.split('#').pop();
-        switch(action){
-          case 'save':
-            $scope.createUser();
-            break;
-          case 'discard':
-            $scope.form.$setPristine();
-            $location.path(targetUrl);
-            break;
-          case 'cancel':
-          targetUrl = '/users';
-            break;
-        }
-      });
-      event.preventDefault();
-    }
-  });
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
deleted file mode 100644
index 8146163..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersListCtrl.js
+++ /dev/null
@@ -1,122 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-  .controller('UsersListCtrl',['$scope', 'User', '$modal', '$rootScope', 'UserConstants', '$translate', 'Settings', function($scope, User, $modal, $rootScope, UserConstants, $translate, Settings) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    admin: $t('users.ambariAdmin'),
-    users: $t('common.users').toLowerCase()
-  };
-  $scope.isLoading = false;
-  $scope.users = [];
-  $scope.usersPerPage = 10;
-  $scope.currentPage = 1;
-  $scope.totalUsers = 1;
-  $scope.currentNameFilter = '';
-  $scope.maxVisiblePages=20;
-  $scope.tableInfo = {
-    total: 0,
-    showed: 0
-  };
-  $scope.isNotEmptyFilter = true;
-
-  $scope.pageChanged = function() {
-    $scope.loadUsers();
-  };
-  $scope.usersPerPageChanges = function() {
-    $scope.resetPagination();
-  };
-
-  $scope.loadUsers = function(){
-    $scope.isLoading = true;
-    User.list({
-      currentPage: $scope.currentPage,
-      usersPerPage: $scope.usersPerPage,
-      searchString: $scope.currentNameFilter,
-      user_type: $scope.currentTypeFilter.value,
-      active: $scope.currentActiveFilter.value,
-      admin: $scope.adminFilter
-    }).then(function(data) {
-      $scope.isLoading = false;
-      $scope.totalUsers = data.data.itemTotal;
-      $scope.users = data.data.items.map(User.makeUser);
-      $scope.tableInfo.showed = data.data.items.length;
-      $scope.tableInfo.total = data.data.itemTotal;
-    });
-  };
-
-  $scope.resetPagination = function() {
-    $scope.currentPage = 1;
-    $scope.loadUsers();
-  };
-
-  $scope.activeFilterOptions = [
-    {label: $t('common.all'), value: '*'},
-    {label: $t('users.active'), value: true},
-    {label: $t('users.inactive'), value:false}
-  ];
-  $scope.currentActiveFilter = $scope.activeFilterOptions[0];
-
-  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
-    .concat(Object.keys(UserConstants.TYPES).map(function(key) {
-      return {
-        label: $t(UserConstants.TYPES[key].LABEL_KEY),
-        value: UserConstants.TYPES[key].VALUE
-      };
-    }));
-
-  $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
-  $scope.adminFilter = false;
-  $scope.toggleAdminFilter = function() {
-    $scope.adminFilter = !$scope.adminFilter;
-    $scope.resetPagination();
-    $scope.loadUsers();
-  };
-
-  $scope.clearFilters = function () {
-    $scope.currentNameFilter = '';
-    $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-    $scope.currentActiveFilter = $scope.activeFilterOptions[0];
-    $scope.adminFilter = false;
-    $scope.resetPagination();
-  };
-
-  $scope.loadUsers();
-
-  $scope.$watch(
-    function (scope) {
-      return Boolean(scope.currentNameFilter || (scope.currentActiveFilter && scope.currentActiveFilter.value !== '*')
-        || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*') || $scope.adminFilter);
-    },
-    function (newValue, oldValue, scope) {
-      scope.isNotEmptyFilter = newValue;
-    }
-  );
-
-  $rootScope.$watch(function(scope) {
-    return scope.LDAPSynced;
-  }, function(LDAPSynced) {
-    if(LDAPSynced === true){
-      $rootScope.LDAPSynced = false;
-      $scope.loadUsers();
-    }
-  });
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
deleted file mode 100644
index 200872e..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/users/UsersShowCtrl.js
+++ /dev/null
@@ -1,290 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('UsersShowCtrl', ['$scope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', function($scope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate) {
-
-  var $t = $translate.instant;
-
-  $scope.constants = {
-    user: $t('common.user'),
-    status: $t('users.status'),
-    admin: $t('users.admin'),
-    password: $t('users.password'),
-    view: $t('common.view').toLowerCase(),
-    cluster: $t('common.cluster').toLowerCase()
-  };
-
-  function loadUserInfo(){
-    User.get($routeParams.id).then(function(data) {
-      $scope.user = User.makeUser(data).Users;
-      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
-      $scope.editingGroupsList = angular.copy($scope.user.groups);
-    });
-  }
-
-  loadUserInfo();
-  $scope.user;
-  $scope.isCurrentUser = true;
-  $scope.dataLoaded = false;
-
-  $scope.isGroupEditing = false;
-  $scope.enableGroupEditing = function() {
-    $scope.isGroupEditing = true;
-    $scope.editingGroupsList = angular.copy($scope.user.groups);
-  };
-
-  $scope.$watch(function() {
-    return $scope.editingGroupsList;
-  }, function(newValue) {
-    if(newValue){
-      if( !angular.equals(newValue, $scope.user.groups) ){
-        $scope.updateGroups();
-      }
-    }
-  }, true);
-
-  $scope.updateGroups = function() {
-    var groups = $scope.editingGroupsList.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
-    var diff = getDifference($scope.user.groups, groups);
-    var promises = [];
-    // Remove user from groups
-    angular.forEach(diff.del, function(groupName) {
-      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function(data) {
-        Alert.error($t('users.alerts.removeUserError'), data.data.message);
-      }));
-    });
-    // Add user to groups
-    angular.forEach(diff.add, function(groupName) {
-      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function(data) {
-        Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
-      }));
-    });
-    $q.all(promises).then(function() {
-      loadUserInfo();
-    });
-    $scope.isGroupEditing = false;
-  };
-
-  $scope.getUserMembership = function(userType) {
-    if(userType) {
-	return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
-    }
-  };
-
-  $scope.cancelUpdate = function() {
-    $scope.isGroupEditing = false;
-    $scope.editingGroupsList = '';
-  };
-
-  $scope.openChangePwdDialog = function() {
-    var modalInstance = $modal.open({
-      templateUrl: 'views/users/modals/changePassword.html',
-      resolve: {
-        userName: function() {
-          return $scope.user.user_name;
-        }
-      },
-      controller: ['$scope', 'userName', function($scope, userName) {
-        $scope.passwordData = {
-          password: '',
-          currentUserPassword: ''
-        };
-
-        $scope.form = {};
-        $scope.userName = userName;
-
-        $scope.ok = function() {
-          $scope.form.passwordChangeForm.submitted = true;
-          if($scope.form.passwordChangeForm.$valid){
-
-            modalInstance.close({
-              password: $scope.passwordData.password, 
-              currentUserPassword: $scope.passwordData.currentUserPassword
-            });
-          }
-        };
-        $scope.cancel = function() {
-          modalInstance.dismiss('cancel');
-        };
-      }]
-    });
-
-    modalInstance.result.then(function(data) {
-      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function() {
-        Alert.success($t('users.alerts.passwordChanged'));
-      }).catch(function(data) {
-        Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
-      });
-    }); 
-  };
-
-  $scope.toggleUserActive = function() {
-    if(!$scope.isCurrentUser){
-      var newStatusKey = $scope.user.active ? 'inactive' : 'active',
-        newStatus = $t('users.' + newStatusKey).toLowerCase();
-      ConfirmationModal.show(
-        $t('users.changeStatusConfirmation.title'),
-        $t('users.changeStatusConfirmation.message', {
-          userName: $scope.user.user_name,
-          status: newStatus
-        })
-      ).then(function() {
-        User.setActive($scope.user.user_name, $scope.user.active)
-          .catch(function(data) {
-            Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
-            $scope.user.active = !$scope.user.active;
-          });
-      })
-      .catch(function() {
-        $scope.user.active = !$scope.user.active;
-      });
-    }
-  };    
-  $scope.toggleUserAdmin = function() {
-    if(!$scope.isCurrentUser){
-      var action = $scope.user.admin ?
-        $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
-      ConfirmationModal.show(
-        $t('users.changePrivilegeConfirmation.title'),
-        $t('users.changePrivilegeConfirmation.message', {
-          action: action,
-          userName: $scope.user.user_name
-        })
-      ).then(function() {
-        User.setAdmin($scope.user.user_name, $scope.user.admin)
-        .then(function() {
-          loadPrivileges();
-        })
-        .catch(function (data) {
-          Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
-          $scope.user.admin = !$scope.user.admin;
-        });
-      })
-      .catch(function() {
-        $scope.user.admin = !$scope.user.admin;
-      });
-
-    }
-  };
-
-  $scope.removePrivilege = function(name, privilege) {
-    var privilegeObject = {
-        id: privilege.privilege_id,
-        view_name: privilege.view_name,
-        version: privilege.version,
-        instance_name: name
-    };
-    View.deletePrivilege(privilegeObject).then(function() {
-      loadPrivileges();
-    });
-  };
-
-  $scope.deleteUser = function() {
-    ConfirmationModal.show(
-      $t('common.delete', {
-        term: $t('common.user')
-      }),
-      $t('common.deleteConfirmation', {
-        instanceType: $t('common.user').toLowerCase(),
-        instanceName: '"' + $scope.user.user_name + '"'
-      })
-    ).then(function() {
-      Cluster.getPrivilegesForResource({
-        nameFilter : $scope.user.user_name,
-        typeFilter : {value: 'USER'}
-      }).then(function(data) {
-        var clusterPrivilegesIds = [];
-        var viewsPrivileges = [];
-        if (data.items && data.items.length) {
-          angular.forEach(data.items[0].privileges, function(privilege) {
-            if (privilege.PrivilegeInfo.principal_type === 'USER') {
-              if (privilege.PrivilegeInfo.type === 'VIEW') {
-                viewsPrivileges.push({
-                  id: privilege.PrivilegeInfo.privilege_id,
-                  view_name: privilege.PrivilegeInfo.view_name,
-                  version: privilege.PrivilegeInfo.version,
-                  instance_name: privilege.PrivilegeInfo.instance_name
-                });
-              } else {
-                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
-              }
-            }
-          });
-        }
-        User.delete($scope.user.user_name).then(function() {
-          $location.path('/users');
-          if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
-          }
-          angular.forEach(viewsPrivileges, function(privilege) {
-            View.deletePrivilege(privilege);
-          });
-        });
-      });
-    });
-  };
-
-  // Load privileges
-  function loadPrivileges(){
-    User.getPrivileges($routeParams.id).then(function(data) {
-      var privileges = {
-        clusters: {},
-        views: {}
-      };
-      angular.forEach(data.data.items, function(privilege) {
-        privilege = privilege.PrivilegeInfo;
-        if(privilege.type === 'CLUSTER'){
-          // This is cluster
-          if (privileges.clusters[privilege.cluster_name]) {
-            var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
-            var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
-            // replace when cur is a more powerful role
-            if (curIndex < preIndex) {
-              privileges.clusters[privilege.cluster_name] = privilege;
-            }
-          } else {
-            privileges.clusters[privilege.cluster_name] = privilege;
-          }
-        } else if ( privilege.type === 'VIEW'){
-          privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
-          privileges.views[privilege.instance_name].version = privilege.version;
-          privileges.views[privilege.instance_name].view_name = privilege.view_name;
-          privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
-          if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) == -1) {
-            privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
-          }
-        }
-      });
-
-      $scope.privileges = data.data.items.length ? privileges : null;
-      $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
-      $scope.noViewPriv = $.isEmptyObject(privileges.views);
-      $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
-      $scope.dataLoaded = true;
-
-    }).catch(function(data) {
-      Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
-    });
-  }
-  loadPrivileges();
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
index 1967dfa..de3968d 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
@@ -101,6 +101,7 @@ angular.module('ambariAdminConsole')
     'common.admin': 'Admin',
     'common.actions': 'Actions',
     'common.error': 'Error',
+    'common.select': 'Select',
 
     'common.clusterNameChangeConfirmation.title': 'Confirm Cluster Name Change',
     'common.clusterNameChangeConfirmation.message': 'Are you sure you want to change the cluster name to {{clusterName}}?',
@@ -276,6 +277,8 @@ angular.module('ambariAdminConsole')
 
     'groups.createLocal': 'Add Groups',
     'groups.name': 'Group name',
+    'groups.role': 'Add roles to this group',
+    'groups.addUsers': 'Add users to this group',
     'groups.members': 'Members',
     'groups.membersPlural': '{{n}} member{{n == 1 ? "" : "s"}}',
 
@@ -285,7 +288,7 @@ angular.module('ambariAdminConsole')
     'groups.alerts.getGroupsListError': 'Get groups list error',
 
     'users.username': 'Username',
-    'users.userName': 'User name',
+    'users.user.name': 'User name',
     'users.admin': 'Admin',
     'users.ambariAdmin': 'Ambari Admin',
     'users.ambariClusterURL': 'Ambari Cluster URL',
@@ -300,7 +303,11 @@ angular.module('ambariAdminConsole')
     'users.inactive': 'Inactive',
     'users.status': 'Status',
     'users.password': 'Password',
+    'users.role': 'Add roles for this user (Cluster Operator/Service Admin)',
+    'users.confirmPassword': 'Confirm Password',
     'users.passwordConfirmation': 'Password сonfirmation',
+    'users.isAmbariAdmin': 'Is this user an Ambari Admin?',
+    'users.isActive': 'Deactivate this user?',
     'users.userIsAdmin': 'This user is an Ambari Admin and has all privileges.',
     'users.showAll': 'Show all users',
     'users.showAdmin': 'Show only admin users',

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
index dabc57a..c8d0e96 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/routes.js
@@ -38,51 +38,25 @@ angular.module('ambariAdminConsole')
       controller: 'LoginActivitiesMainCtrl'
     }
   },
-  users: {
-    list: {
-      url: '/users',
-      templateUrl: 'views/users/list.html',
-      controller: 'UsersListCtrl',
+  userManagement: {
+    main: {
+      url: '/userManagement',
+      templateUrl: 'views/userManagement/main.html',
+      controller: 'UserManagementCtrl',
       label: 'Users'
     },
-    edit: {
+    editUser: {
       url: '/users/:id/edit',
-      templateUrl: 'views/users/create.html',
-      controller: 'UsersCreateCtrl',
+      templateUrl: 'views/userManagement/userEdit.html',
+      controller: 'UserEditCtrl',
       label: 'Users'
     },
-    create: {
-      url: '/users/new',
-      templateUrl: 'views/users/create.html',
-      controller: 'UsersCreateCtrl',
-      label: 'Users'
-    },
-    show: {
-      url: '/users/:id*',
-      templateUrl: 'views/users/show.html',
-      controller: 'UsersShowCtrl',
-      label: 'Users'
-    }
-  },
-  groups: {
-    list: {
-      url: '/groups',
-      templateUrl: 'views/groups/list.html',
-      controller: 'GroupsListCtrl',
-      label: 'Groups'
-    },
-    edit: {
+    editGroup: {
       url: '/groups/:id/edit',
-      templateUrl: 'views/groups/edit.html',
-      controller: 'GroupsEditCtrl',
+      templateUrl: 'views/userManagement/groupEdit.html',
+      controller: 'GroupEditCtrl',
       label: 'Groups'
     },
-    create: {
-      url: '/groups/new',
-      templateUrl: 'views/groups/create.html',
-      controller: 'GroupsCreateCtrl',
-      label: 'Groups'
-    }
   },
   views: {
     list: {
@@ -157,20 +131,9 @@ angular.module('ambariAdminConsole')
     }
   },
   clusters: {
-    manageAccess: {
-      url: '/clusters/:id/manageAccess',
-      templateUrl: 'views/clusters/manageAccess.html',
-      controller: 'ClustersManageAccessCtrl',
-      label: 'Roles'
-    },
-    userAccessList: {
-      url: '/clusters/:id/userAccessList',
-      templateUrl: 'views/clusters/userAccessList.html',
-      controller: 'UserAccessListCtrl'
-    },
     clusterInformation: {
       url: '/clusterInformation',
-      templateUrl: 'views/clusterInformation.html',
+      templateUrl: 'views/clusters/clusterInformation.html',
       controller: 'ClusterInformationCtrl',
       label: 'Cluster Information'
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
index ac50653..47015d1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
@@ -94,9 +94,10 @@ angular.module('ambariAdminConsole')
      * @returns {Object}
      */
     makeUser: function(user) {
-      user.Users.encoded_name = encodeURIComponent(user.Users.user_name);
+      user.Users.encodedName = encodeURIComponent(user.Users.user_name);
       user.Users.userTypeName = $t(UserConstants.TYPES[user.Users.user_type].LABEL_KEY);
-      user.Users.ldap_user = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
+      user.Users.ldapUser = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
+      user.Users.role = user.privileges.length ? user.privileges[0].PrivilegeInfo.privilege_id : null;
 
       return user;
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
index 94bdf11..91b2fb1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
@@ -247,6 +247,9 @@ a.gotoinstance{
 .hide-soft{
   display: none;
 }
+.nowrap {
+  white-space: nowrap;
+}
 .visible{
   display: block;
 }
@@ -386,16 +389,6 @@ a.gotoinstance{
 .search-container input {
   font-weight: normal;
 }
-.groups-pane .search-container .close{
-  top: 32px;
-}
-
-.groups-pane table thead th{
-  border-top: 0;
-}
-.groups-pane table thead tr:first-child th{
-  border: 0;
-}
 
 ul.nav li > a{
   cursor: pointer;
@@ -464,16 +457,6 @@ table.no-border tr td{
   margin-top: 0;
 }
 
-.groups-pane table ul{
-  list-style-type: none;
-  margin: 0;
-  padding: 0;
-}
-.groups-pane table ul li {
-  margin: 0;
-  padding: 0;
-}
-
 .property-form label{
   word-wrap: break-word;
   text-overflow: ellipsis;
@@ -539,6 +522,7 @@ button.btn.btn-xs{
   font-size: 12px;
   line-height: 1.5;
   border-radius: 3px;
+  height: 24px;
 }
 
 a.btn-primary, a.btn-primary:focus {
@@ -617,13 +601,13 @@ a.alert-link, a.alert-link:hover, a.alert-link:visited{
   box-sizing: border-box;
 }
 
-.fix-bottom{
+.fix-bottom th {
   border-bottom: none !important;;
   border-top: none !important;
   border-width: 0;
 }
 
-.fix-top{
+.fix-top th {
   border-top: none !important;
   border-width: 0;
 }
@@ -1334,3 +1318,21 @@ body {
 .navigation-bar-fit-height {
   z-index: 1001;
 }
+
+.entity-actions a {
+  color: inherit;
+  font-size: 16px;
+  cursor: pointer;
+  padding: 0 5px;
+}
+
+td.entity-actions,
+th.entity-actions {
+  width: 10%;
+}
+
+.entity-actions a:hover,
+.entity-actions a:visited:hover,
+.entity-actions a:focus:hover {
+  text-decoration: none;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
new file mode 100644
index 0000000..77c94ac
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+#user-management .table th {
+  vertical-align: baseline;
+}
+
+#user-management .nav.nav-tabs {
+  margin-bottom: 0;
+}
+
+#user-management .users-pane,
+#user-management .groups-pane {
+  margin-top: -35px;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
index 58583de..9bb84df 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/views.css
@@ -16,24 +16,6 @@
  * limitations under the License.
  */
 
-.view-instance-actions a {
-  color: inherit;
-  font-size: 16px;
-  cursor: pointer;
-  padding: 0 5px;
-}
-
-td.view-instance-actions,
-th.view-instance-actions {
-  width: 10%;
-}
-
-.view-instance-actions a:hover,
-.view-instance-actions a:visited:hover,
-.view-instance-actions a:focus:hover {
-  text-decoration: none;
-}
-
 #create-instance-form i {
   cursor: pointer;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
index 2ff0fc4..04901f1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/viewsList.html
@@ -29,24 +29,24 @@
     <table class="table table-striped table-hover">
         <thead>
         <tr class="fix-bottom">
-            <th class="fix-bottom col-md-2">
+            <th class="col-md-2">
                 <span>{{'common.name' | translate}}</span>
             </th>
-            <th class="fix-bottom col-md-3">
+            <th class="col-md-3">
                 <span>{{'urls.url' | translate}}</span>
             </th>
-            <th class="fix-bottom col-md-2">
+            <th class="col-md-2">
                 <span>{{'views.table.viewType' | translate}}</span>
             </th>
-            <th class="fix-bottom col-md-2">
+            <th class="col-md-2">
                 <span>{{'urls.viewInstance' | translate}}</span>
             </th>
-            <th class="fix-bottom col-md-2 view-instance-actions">
+            <th class="col-md-2 entity-actions">
                 <span>{{'common.actions' | translate}}</span>
             </th>
         </tr>
-        <tr>
-            <th class="fix-top">
+        <tr class="fix-top">
+            <th>
                 <div class="search-container">
                     <input type="text" class="form-control" placeholder="{{'common.any' | translate}}"
                            ng-model="instanceNameFilter" ng-change="filterInstances()">
@@ -57,7 +57,7 @@
                     </button>
                 </div>
             </th>
-            <th class="fix-top">
+            <th>
                 <div class="search-container">
                     <input type="text" class="form-control" placeholder="{{'common.any' | translate}}"
                            ng-model="instanceUrlFilter" ng-change="filterInstances()">
@@ -68,17 +68,15 @@
                     </button>
                 </div>
             </th>
-            <th class="fix-top">
+            <th>
                 <select class="form-control typefilter v-small-input"
                         ng-model="instanceTypeFilter"
                         ng-options="item.label for item in typeFilterOptions"
                         ng-change="filterInstances()">
                 </select>
             </th>
-            <th class="fix-top">
-            </th>
-            <th class="fix-top">
-            </th>
+            <th></th>
+            <th></th>
         </tr>
         </thead>
 
@@ -98,7 +96,7 @@
             <td>
                 <span>{{instance.instance_name}}</span>
             </td>
-            <td class="view-instance-actions" ng-switch="instance.versionObj.status">
+            <td class="entity-actions" ng-switch="instance.versionObj.status">
                 <span ng-switch-when="PENDING">
                     <i class="viewstatus pending"></i>
                     {{'views.pending' | translate}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
deleted file mode 100644
index ead73c3..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusterInformation.html
+++ /dev/null
@@ -1,87 +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.
--->
-
-<div id="cluster-information">
-  <div ng-show="cluster.Clusters.provisioning_state !== 'INSTALLED'">
-    <div class="welcome-header">
-      <h1>{{'main.title' | translate}}</h1>
-      <span>{{'main.noClusterDescription' | translate}}</span>
-    </div>
-    <div class="create-cluster-section">
-      <h2>{{'main.createCluster.title' | translate}}</h2>
-      <div>
-        <span>
-          {{'main.createCluster.description' | translate}}
-        </span>
-      </div>
-      <div><i class="fa fa-cloud" aria-hidden="true"></i></div>
-      <div>
-        <a href="{{fromSiteRoot('/#/installer/step0')}}" class="btn btn-primary">
-          {{'main.createCluster.launchInstallWizard' | translate}}
-        </a>
-      </div>
-    </div>
-  </div>
-
-  <div ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
-    <form class="row" name="editClusterNameForm" ng-submit="confirmClusterNameChange()">
-      <div class="form-group col-xs-4 cluster-name"
-           ng-class="{'has-error': editClusterNameForm.clusterName.$invalid}">
-        <label for="clusterName">{{'views.clusterName' | translate}}*</label>
-        <input type="text"
-               class="form-control"
-               id="clusterName"
-               name="clusterName"
-               ng-change="toggleSaveButton()"
-               ng-model="edit.clusterName"
-               required
-               autofocus
-               ng-pattern="/^\w*$/"
-               ng-maxlength="80"
-               tooltip="{{'common.renameClusterTip' | translate}}"
-               tooltip-trigger="focus"
-               tooltip-placement="bottom"
-               ng-class="{edited: isClusterNameEdited}">
-        <button
-          type="submit"
-          ng-class="{'disabled': editClusterNameForm.clusterName.$invalid}"
-          class="btn btn-default pull-right"
-          ng-show="isClusterNameEdited">
-          {{'common.controls.save' | translate}}
-        </button>
-      </div>
-    </form>
-    <div>
-      <div class="row dev-blueprint">
-        <div class="col-sm-11"><span>{{'clusters.devBlueprint' | translate}}</span></div>
-        <div class="col-sm-1">
-          <div class="btn btn-default pull-right" ng-click="downloadBlueprint()">{{"common.download" | translate}}
-          </div>
-        </div>
-      </div>
-      <textarea type="text"
-                rows="20"
-                class="form-control"
-                name="blueprint_text"
-                ng-model="blueprint"
-                ng-disabled="true"
-                ng-readonly="true">
-      </textarea>
-    </div>
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
new file mode 100644
index 0000000..ead73c3
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/clusterInformation.html
@@ -0,0 +1,87 @@
+<!--
+* 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 id="cluster-information">
+  <div ng-show="cluster.Clusters.provisioning_state !== 'INSTALLED'">
+    <div class="welcome-header">
+      <h1>{{'main.title' | translate}}</h1>
+      <span>{{'main.noClusterDescription' | translate}}</span>
+    </div>
+    <div class="create-cluster-section">
+      <h2>{{'main.createCluster.title' | translate}}</h2>
+      <div>
+        <span>
+          {{'main.createCluster.description' | translate}}
+        </span>
+      </div>
+      <div><i class="fa fa-cloud" aria-hidden="true"></i></div>
+      <div>
+        <a href="{{fromSiteRoot('/#/installer/step0')}}" class="btn btn-primary">
+          {{'main.createCluster.launchInstallWizard' | translate}}
+        </a>
+      </div>
+    </div>
+  </div>
+
+  <div ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
+    <form class="row" name="editClusterNameForm" ng-submit="confirmClusterNameChange()">
+      <div class="form-group col-xs-4 cluster-name"
+           ng-class="{'has-error': editClusterNameForm.clusterName.$invalid}">
+        <label for="clusterName">{{'views.clusterName' | translate}}*</label>
+        <input type="text"
+               class="form-control"
+               id="clusterName"
+               name="clusterName"
+               ng-change="toggleSaveButton()"
+               ng-model="edit.clusterName"
+               required
+               autofocus
+               ng-pattern="/^\w*$/"
+               ng-maxlength="80"
+               tooltip="{{'common.renameClusterTip' | translate}}"
+               tooltip-trigger="focus"
+               tooltip-placement="bottom"
+               ng-class="{edited: isClusterNameEdited}">
+        <button
+          type="submit"
+          ng-class="{'disabled': editClusterNameForm.clusterName.$invalid}"
+          class="btn btn-default pull-right"
+          ng-show="isClusterNameEdited">
+          {{'common.controls.save' | translate}}
+        </button>
+      </div>
+    </form>
+    <div>
+      <div class="row dev-blueprint">
+        <div class="col-sm-11"><span>{{'clusters.devBlueprint' | translate}}</span></div>
+        <div class="col-sm-1">
+          <div class="btn btn-default pull-right" ng-click="downloadBlueprint()">{{"common.download" | translate}}
+          </div>
+        </div>
+      </div>
+      <textarea type="text"
+                rows="20"
+                class="form-control"
+                name="blueprint_text"
+                ng-model="blueprint"
+                ng-disabled="true"
+                ng-readonly="true">
+      </textarea>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
deleted file mode 100644
index a399eff..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/manageAccess.html
+++ /dev/null
@@ -1,63 +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.
--->
-    
-<div class="cluster-manage-access-pane">
-  <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li class="active">{{clusterName}} {{'common.roles' | translate}}</li>
-    </ol>
-  </div>
-  <hr>
-  <div class="pull-right">
-    <div class="layout-switch-icon-wrapper">
-      <i class="glyphicon glyphicon-th-large layout-switch-icon"></i>
-      <p class="label-block">{{'common.blockViewLabel' | translate}}</p>
-    </div>
-    <div class="layout-switch-icon-wrapper disabled">
-      <i class="glyphicon glyphicon-list layout-switch-icon" ng-click="switchToList()" tooltip-html-unsafe="{{'clusters.switchToList' | translate}}"></i>
-      <p class="label-list">{{'common.listViewLabel' | translate}}</p>
-    </div>
-  </div>
-  <table class="table">
-    <thead>
-      <tr>
-        <th class="col-sm-2" width="20%">
-          <label>{{'common.roles' | translate}}</label>&nbsp;
-          <i class="glyphicon glyphicon-question-sign green-icon cursor-pointer" ng-click="showHelpPage()"></i>
-        </th>
-        <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("common.users")}'}}</label></th>
-        <th class="col-sm-5" width="40%"><label>{{'clusters.assignRoles' | translate: '{term: getConstant("common.groups")}'}}</label></th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr ng-repeat="permission in permissions">
-        <td><label class="" tooltip="{{permission.PermissionInfo.permission_name}}">{{permission.PermissionInfo.permission_label}}</label></td>
-        <td>
-          <div class="" ng-switch="isEditMode">
-            <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].USER" resource-type="User" editable="true"></editable-list>
-          </div>
-        </td>
-        <td>
-          <div class="" ng-switch="isEditMode">
-            <editable-list items-source="permissionsEdit[permission.PermissionInfo.permission_name].GROUP" resource-type="Group" editable="true"></editable-list>
-          </div>
-        </td>
-      </tr>
-    </tbody>
-  </table>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
deleted file mode 100644
index 8b29157..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/clusters/userAccessList.html
+++ /dev/null
@@ -1,102 +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.
--->
-
-<div class="users-pane">
-  <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li class="active">{{clusterId}} {{'common.roles' | translate}}</li>
-    </ol>
-  </div>
-  <hr>
-  <div class="pull-right">
-    <div class="layout-switch-icon-wrapper disabled">
-      <i class="glyphicon glyphicon-th-large layout-switch-icon" ng-click="switchToBlock()" tooltip-html-unsafe="{{'clusters.switchToBlock' | translate}}"></i>
-      <p class="label-block">{{'common.blockViewLabel' | translate}}</p>
-    </div>
-    <div class="layout-switch-icon-wrapper">
-      <i class="glyphicon glyphicon-list layout-switch-icon"></i>
-      <p class="label-list">{{'common.listViewLabel' | translate}}</p>
-    </div>
-  </div>
-  <ul class="nav nav-pills">
-    <li ng-class="{'active': isUserActive}"><a ng-click="switchToUser()">{{'common.users' | translate}}</a></li>
-    <li ng-class="{'active': !isUserActive}"><a ng-click="switchToGroup()">{{'common.groups' | translate}}</a></li>
-  </ul>
-  <br/>
-  <table class="table table-striped table-hover">
-    <thead>
-    <tr>
-      <th class="role-name-column">
-        <div class="search-container">
-          <label for="">{{'common.name' | translate}}</label>
-          <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
-          <button type="button" class="close clearfilter" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()">
-            <span aria-hidden="true">&times;</span><span class="sr-only">{{'common.controls.close' | translate}}</span>
-          </button>
-        </div>
-      </th>
-      <th>
-        <label for="">{{'clusters.role' | translate}}</label>&nbsp;
-        <i class="glyphicon glyphicon-question-sign green-icon cursor-pointer" ng-click="showHelpPage()"></i>
-        <select class="form-control statusfilter"
-                ng-model="currentRoleFilter"
-                ng-options="item.label for item in roleFilterOptions"
-                ng-change="resetPagination()">
-        </select>
-      </th>
-    </tr>
-    </thead>
-    <tbody>
-    <tr ng-repeat="user in users">
-      <td>
-        <a href="#/{{user.url}}">{{user.principal_name}}</a>
-      </td>
-      <td>
-        <div ng-show="!user.editable">{{user.permission_label}}</div>
-        <select class="form-control role-select" ng-show="user.editable" ng-model="user.permission_name"
-                ng-options="role.permission_name as role.permission_label for role in roleValueOptions">
-        </select>
-        <span ng-show="user.principal_type != $parent.currentTypeFilter.value">&nbsp;{{'common.fromGroupMark' | translate}}</span>
-        <span ng-show="user.permission_name != user.original_perm">
-          <button class="btn btn-default btn-xs cancel" ng-click="cancel(user)">
-            <span class="glyphicon glyphicon-remove cancel"></span>
-          </button>
-          <button class="btn btn-primary btn-xs" ng-click="save(user)">
-            <span class="glyphicon glyphicon-ok"></span>
-          </button>
-        </span>
-      </td>
-    </tr>
-    </tbody>
-  </table>
-  <div class="alert alert-info col-sm-12" ng-show="!users.length">
-    {{'common.alerts.nothingToDisplay' | translate: '{term: (isUserActive ? constants.users : constants.groups)}'}}
-  </div>
-  <div class="col-sm-12 table-bar">
-    <div class="pull-left filtered-info">
-      <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: (isUserActive ? constants.users : constants.groups)}'}}</span>
-      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
-    </div>
-    <div class="pull-right left-margin">
-      <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
-    </div>
-    <div class="pull-right">
-      <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
-    </div>
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
deleted file mode 100644
index 9a0e0fb..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/create.html
+++ /dev/null
@@ -1,43 +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.
--->
-<ol class="breadcrumb">
-  <li><a href="#/groups">{{'common.groups' | translate}}</a></li>
-  <li class="active">{{'groups.createLocal' | translate}}</li>
-</ol>
-<hr>
-<form class="form-horizontal" role="form" novalidate name="form" autocomplete="off">
-  <div class="form-group" ng-class="{'has-error' : (form.group_name.$error.required || form.group_name.$error.pattern) && form.submitted}">
-    <label for="groupname" class="col-sm-2 control-label">{{'groups.name' | translate}}</label>
-    <div class="col-sm-10">
-      <input type="text" id="groupname" class="form-control groupname-input" name="group_name" placeholder="{{'groups.name' | translate}}" ng-model="group.group_name" required ng-pattern="/^([a-zA-Z0-9._\s]+)$/" autocomplete="off">
-      <div class="alert alert-danger top-margin" ng-show="form.group_name.$error.required && form.submitted">
-        {{'common.alerts.fieldIsRequired' | translate}}
-      </div>
-      <div class="alert alert-danger top-margin" ng-show="form.group_name.$error.pattern && form.submitted">
-        {{'common.alerts.onlySimpleChars' | translate}}
-      </div>
-    </div>
-  </div>
-  <div class="form-group">
-    <div class="col-sm-offset-2 col-sm-10">
-      <button class="btn btn-primary groupcreate-btn pull-right left-margin" ng-click="createGroup()">{{'common.controls.save' | translate}}</button>
-      <a href ng-click="cancel()" class="btn btn-default pull-right cancel-button">{{'common.controls.cancel' | translate}}</a>
-    </div>
-  </div>
-      
-</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
deleted file mode 100644
index 1aafd03..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/edit.html
+++ /dev/null
@@ -1,98 +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.
--->
-  
-<div class="clearfix">
-  <ol class="breadcrumb pull-left">
-    <li><a href="#/groups">{{'common.groups' | translate}}</a></li>
-    <li class="active">{{group.group_name}}</li>
-  </ol>
-  <div class="pull-right top-margin-4">
-  <div ng-switch="group.group_type != 'LOCAL'">
-      <button ng-switch-when="true" class="btn disabled deletegroup-btn deleteuser-btn" tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">{{'common.delete' | translate: '{term: constants.group}'}}</button>
-      <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">{{'common.delete' | translate: '{term: constants.group}'}}</button>
-    </div>
-      
-  </div>
-</div>
-<hr>
-<form class="form-horizontal group-edit" role="form" novalidate name="form" >
-  <div class="form-group">
-    <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
-    <div class="col-sm-10">
-      <label for="" class="control-label">{{group.groupTypeName | translate}}</label>
-    </div>
-  </div>
-  <div class="form-group">
-    <label for="members" class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
-    <div class="col-sm-10">
-      <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
-    </div>
-  </div>
-
-  <div class="form-group">
-      <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
-      <div class="col-sm-10">
-        <table class="table" ng-hide="hidePrivileges">
-          <thead>
-            <tr>
-              <th>{{'common.cluster' | translate}}</th>
-              <th>{{'common.clusterRole' | translate}}</th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.clusters">
-              <td>
-                <span class="glyphicon glyphicon-cloud"></span> 
-                <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
-              </td>
-              <td>
-                <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
-              </td>
-            </tr>
-            <tr>
-              <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
-            </tr>
-          </tbody>
-          <thead class="view-permission-header">
-            <tr>
-              <th>{{'common.view' | translate}}</th>
-              <th>{{'common.viewPermissions' | translate}}</th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.views">
-              <td>
-                <span class="glyphicon glyphicon-th"></span>
-                <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
-              </td>
-              <td>
-                <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
-              </td>
-              <td>
-                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
-              </td>
-            </tr>
-            <tr>
-              <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
-            </tr>
-          </tbody>
-        </table>
-        <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
-      </div>
-    </div>
-</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
deleted file mode 100644
index b39f55d..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/groups/list.html
+++ /dev/null
@@ -1,80 +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.
--->
-<div class="groups-pane">
-  <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li class="active">{{'common.groups' | translate}}</li>
-    </ol>
-    <div class="pull-right top-margin-4">
-      <link-to route="groups.create" class="btn btn-default creategroup-btn">
-        {{'groups.createLocal' | translate}}
-      </link-to>
-    </div>
-  </div>
-  <table class="table table-striped table-hover col-sm-12">
-    <thead>
-      <tr>
-        <th class="col-sm-8">
-          <div class="search-container">
-            <label for="">{{'groups.name' | translate}}</label>
-            <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
-            <button type="button" class="close" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()"><span aria-hidden="true">&times;</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
-          </div>
-        </th>
-        <th class="col-sm-2">
-          <label for="">{{'common.type' | translate}}</label>
-          <select class="form-control typefilter"
-            ng-model="currentTypeFilter"
-            ng-options="item.label for item in typeFilterOptions"
-            ng-change="resetPagination();">
-          </select>
-        </th>
-        <th class="col-sm-2 vertical-top">
-          <label for="">{{'groups.members' | translate}}</label>
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr ng-repeat="group in groups">
-        <td class="col-sm-8">
-          <link-to route="groups.edit" class="link-to-group" id="{{group.group_name}}">{{group.group_name}}</link-to>
-        </td>
-        <td class="col-sm-2">{{group.groupTypeName | translate}}</td>
-        <td class="col-sm-2">{{'groups.membersPlural' | translate: '{n: group.members && group.members.length || 0}'}}</td>
-      </tr>
-    </tbody>
-  </table>
-  <div ng-if="isLoading" class="spinner-container">
-    <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
-  </div>
-  <div class="alert empty-table-alert col-sm-12" ng-show="!groups.length && !isLoading">
-    {{'common.alerts.nothingToDisplay' | translate: '{term: constants.groups}'}}
-  </div>
-  <div class="col-sm-12 table-bar">
-    <div class="pull-left filtered-info">
-      <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.groups}'}}</span>
-      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
-    </div>
-    <div class="pull-right left-margin">
-      <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
-    </div>
-    <div class="pull-right">
-      <select class="form-control" ng-model="groupsPerPage" ng-change="groupsPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
-    </div>
-  </div>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
index 97dc5d3..98a95cd 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/sideNav.html
@@ -59,25 +59,11 @@
           </li>
         </ul>
       </li>
-      <li class="mainmenu-li dropdown has-sub-menu">
-        <a title="{{'common.userManagement' | translate}}" rel="tooltip" data-placement="right" data-toggle="collapse-sub-menu">
-          <span class="toggle-icon glyphicon glyphicon-menu-down pull-right"></span>
+      <li class="mainmenu-li" ng-class="{active: isActive('userManagement.main')}">
+        <link-to route="userManagement.main" class="userslist-link" title="{{'common.users' | translate}}" rel="tooltip" data-placement="right">
           <i class="navigation-icon fa fa-users" aria-hidden="true"></i>
-          <span class="navigation-menu-item">{{'common.userManagement' | translate}}</span>
-        </a>
-        <ul class="sub-menu nav nav-pills nav-stacked">
-          <li class="submenu-li"
-              ng-class="{active: isActive('clusters.manageAccess') || isActive('clusters.userAccessList')}"
-              ng-show="cluster.Clusters.provisioning_state === 'INSTALLED'">
-            <a href="#/clusters/{{cluster.Clusters.cluster_name}}/manageAccess" class="roles">{{'common.roles' | translate}}</a>
-          </li>
-          <li class="submenu-li" ng-class="{active: isActive('users.list')}">
-            <link-to route="users.list" class="userslist-link">{{'common.users' | translate}}</link-to>
-          </li>
-          <li class="submenu-li" ng-class="{active: isActive('groups.list')}">
-            <link-to route="groups.list" class="groupslist-link">{{'common.groups' | translate}}</link-to>
-          </li>
-        </ul>
+          <span class="navigation-menu-item">{{'common.users' | translate}}</span>
+        </link-to>
       </li>
       <li class="mainmenu-li" ng-class="{active: isActive('views.list')}">
         <link-to route="views.list" class="viewslist-link" title="{{'common.views' | translate}}" rel="tooltip" data-placement="right">

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
new file mode 100644
index 0000000..90a1907
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
@@ -0,0 +1,99 @@
+<!--
+* 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="clearfix">
+  <div class="pull-right">
+    <div ng-switch="group.group_type != 'LOCAL'">
+      <button
+        ng-switch-when="true"
+        class="btn disabled deletegroup-btn"
+        tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">
+        {{'common.delete' | translate: '{term: constants.group}'}}
+      </button>
+      <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">
+        {{'common.delete' | translate: '{term: constants.group}'}}
+      </button>
+    </div>
+  </div>
+</div>
+<form class="form-horizontal group-edit" role="form" novalidate name="form" >
+  <div class="form-group">
+    <label class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+    <div class="col-sm-10">
+      <label class="control-label">{{group.groupTypeName | translate}}</label>
+    </div>
+  </div>
+  <div class="form-group">
+    <label class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
+    <div class="col-sm-10">
+      <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
+    </div>
+  </div>
+
+  <div class="form-group">
+      <label class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
+      <div class="col-sm-10">
+        <table class="table" ng-hide="hidePrivileges">
+          <thead>
+            <tr>
+              <th>{{'common.cluster' | translate}}</th>
+              <th>{{'common.clusterRole' | translate}}</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr ng-repeat="(name, privilege) in privileges.clusters">
+              <td>
+                <span class="glyphicon glyphicon-cloud"></span> 
+                <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
+              </td>
+              <td>
+                <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
+              </td>
+            </tr>
+            <tr>
+              <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
+            </tr>
+          </tbody>
+          <thead class="view-permission-header">
+            <tr>
+              <th>{{'common.view' | translate}}</th>
+              <th>{{'common.viewPermissions' | translate}}</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr ng-repeat="(name, privilege) in privileges.views">
+              <td>
+                <span class="glyphicon glyphicon-th"></span>
+                <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
+              </td>
+              <td>
+                <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
+              </td>
+              <td>
+                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
+              </td>
+            </tr>
+            <tr>
+              <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
+      </div>
+    </div>
+</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
new file mode 100644
index 0000000..d79d14e
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupsList.html
@@ -0,0 +1,94 @@
+<!--
+* 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="groups-pane">
+  <div class="clearfix panel">
+    <button class="btn btn-default creategroup-btn pull-right" ng-click="createGroup()">
+      {{'groups.createLocal' | translate}}
+    </button>
+  </div>
+  <table class="table table-striped table-hover col-sm-12">
+    <thead>
+      <tr>
+        <th class="col-sm-6">
+          <span>{{'groups.name' | translate}}</span>
+        </th>
+        <th class="col-sm-2">
+          <span>{{'common.type' | translate}}</span>
+        </th>
+        <th class="col-sm-2">
+          <span>{{'groups.members' | translate}}</span>
+        </th>
+        <th class="col-sm-2">
+          <span>{{'common.actions' | translate}}</span>
+        </th>
+      </tr>
+      <tr>
+        <th class="col-sm-6">
+          <div class="search-container">
+            <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="filter.name" ng-change="resetPagination()">
+            <button type="button" class="close" ng-show="filter.name" ng-click="filter.name=''; resetPagination()"><span aria-hidden="true">&times;</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
+          </div>
+        </th>
+        <th class="col-sm-2">
+          <select class="form-control typefilter"
+                  ng-model="filter.type"
+                  ng-options="item.label for item in typeFilterOptions"
+                  ng-change="resetPagination();">
+          </select>
+        </th>
+        <th class="col-sm-2"></th>
+        <th class="col-sm-2"></th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr ng-repeat="group in groups">
+        <td class="col-sm-8">
+          <span>{{group.group_name}}</span>
+        </td>
+        <td class="col-sm-2">{{group.groupTypeName | translate}}</td>
+        <td class="col-sm-2">{{'groups.membersPlural' | translate: '{n: group.members && group.members.length || 0}'}}</td>
+        <td class="entity-actions">
+          <link-to route="userManagement.editGroup" class="link-to-group" id="{{group.group_name}}">
+            <i class="fa fa-pencil"></i>
+          </link-to>
+          <a href ng-click="deleteGroup(group)">
+            <i class="fa fa-trash-o"></i>
+          </a>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+  <div ng-if="isLoading" class="spinner-container">
+    <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
+  </div>
+  <div class="alert empty-table-alert col-sm-12" ng-show="!groups.length && !isLoading">
+    {{'common.alerts.nothingToDisplay' | translate: '{term: constants.groups}'}}
+  </div>
+  <div class="col-sm-12 table-bar" ng-show="totalGroups > minRowsToShowPagination">
+    <div class="pull-left filtered-info">
+      <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.groups}'}}</span>
+      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
+    </div>
+    <div class="pull-right left-margin">
+      <pagination class="paginator" total-items="totalGroups" max-size="maxVisiblePages" items-per-page="groupsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
+    </div>
+    <div class="pull-right">
+      <select class="form-control" ng-model="groupsPerPage" ng-change="groupsPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
+    </div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
new file mode 100644
index 0000000..079eefb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
@@ -0,0 +1,36 @@
+<!--
+* 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 id="user-management">
+  <ul class="nav nav-tabs">
+    <li ng-class="{active: activeTab === 'USERS'}">
+      <a ng-click="activeTab = 'USERS'">{{'common.users' | translate}}</a>
+    </li>
+    <li ng-class="{active: activeTab === 'GROUPS'}">
+      <a ng-click="activeTab = 'GROUPS'">{{'common.groups' | translate}}</a>
+    </li>
+  </ul>
+  <div>
+    <div class="users" ng-if="activeTab === 'USERS'">
+      <div ng-include="'views/userManagement/usersList.html'" ng-controller="UsersListCtrl"></div>
+    </div>
+    <div class="groups" ng-if="activeTab === 'GROUPS'">
+      <div ng-include="'views/userManagement/groupsList.html'" ng-controller="GroupsListCtrl"></div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
new file mode 100644
index 0000000..f29d315
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/changePassword.html
@@ -0,0 +1,46 @@
+<!--
+* 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="modal-header">
+  <h3 class="modal-title">{{'users.changePasswordFor' | translate: '{userName: userName}'}}</h3>
+</div>
+<div class="modal-body">
+  <form class="form-horizontal" novalidate name="form.passwordChangeForm" role="form" >
+    <div class="form-group" ng-class="{'has-error' : (form.passwordChangeForm.currentPassword.$error.required && form.passwordChangeForm.submitted)}">
+      <label for="" class="col-sm-4 control-label" >{{'users.yourPassword' | translate}}</label>
+      <div class="col-sm-8">
+        <input type="password" name="currentPassword" class="form-control bottom-margin" placeholder="{{'users.yourPassword' | translate}}" required ng-model="passwordData.currentUserPassword" autocomplete="off">
+        <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
+      </div>
+    </div>
+    <div class="form-group no-margin-bottom" ng-class="{'has-error' : (form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted) || form.passwordChangeForm.confirmPassword.$error.passwordVerify}">
+      <label for="" class="col-sm-4 control-label">{{'users.newPassword' | translate}}:</label>
+      <div class="col-sm-8">
+        <input type="password" class="form-control bottom-margin" name="password" placeholder="{{'users.newPassword' | translate}}" required ng-model="passwordData.password" autocomplete="off">
+        <input type="password" class="form-control bottom-margin" name="confirmPassword" placeholder="{{'users.newPasswordConfirmation' | translate}}" required ng-model="passwordData.passwordConfirmation"
+          password-verify="passwordData.password" autocomplete="off">
+        <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
+        <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
+      </div>
+
+    </div>
+  </form>
+</div>
+<div class="modal-footer">
+  <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+  <button class="btn btn-primary" ng-click="ok()">{{'common.controls.ok' | translate}}</button>
+</div>
\ No newline at end of file


[28/50] [abbrv] ambari git commit: AMBARI-22458 - SNMP Trap should contain sysuptime field filled (unit test fixes) (jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22458 - SNMP Trap should contain sysuptime field filled (unit test fixes) (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/aa652afe
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/aa652afe
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/aa652afe

Branch: refs/heads/branch-3.0-perf
Commit: aa652afe18c26ebbb52ffa1d8ecfad4270a093d7
Parents: 82af6fb
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Tue Nov 28 12:23:31 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue Nov 28 12:31:13 2017 -0500

----------------------------------------------------------------------
 .../dispatchers/AmbariSNMPDispatcherTest.java   | 23 +++++----
 .../AlertNoticeDispatchServiceTest.java         | 53 +++++++++++++++++---
 2 files changed, 59 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/aa652afe/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcherTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcherTest.java b/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcherTest.java
index 0b299f6..14b6216 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcherTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcherTest.java
@@ -21,11 +21,11 @@ package org.apache.ambari.server.notifications.dispatchers;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -36,6 +36,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.ambari.server.notifications.DispatchCallback;
@@ -90,7 +91,7 @@ public class AmbariSNMPDispatcherTest {
         AmbariSNMPDispatcher.SnmpVersion snmpVersion = AmbariSNMPDispatcher.SnmpVersion.SNMPv1;
         Notification notification = mock(AlertNotification.class);
         notification.Callback = mock(DispatchCallback.class);
-        notification.CallbackIds = new ArrayList<>();
+        notification.CallbackIds = mock(List.class);
         Map<String, String> properties = new HashMap<>();
         properties.put(AmbariSNMPDispatcher.PORT_PROPERTY, "3");
         properties.put(AmbariSNMPDispatcher.COMMUNITY_PROPERTY, "4");
@@ -109,7 +110,7 @@ public class AmbariSNMPDispatcherTest {
         AmbariSNMPDispatcher dispatcher = new AmbariSNMPDispatcher(DEFAULT_SNMP_PORT);
         Notification notification = mock(AlertNotification.class);
         notification.Callback = mock(DispatchCallback.class);
-        notification.CallbackIds = new ArrayList<>();
+        notification.CallbackIds = mock(List.class);
         notification.DispatchProperties = new HashMap<>();
         dispatcher.dispatch(notification);
         verify(notification.Callback).onFailure(notification.CallbackIds);
@@ -121,7 +122,7 @@ public class AmbariSNMPDispatcherTest {
         AmbariSNMPDispatcher dispatcher = new AmbariSNMPDispatcher(DEFAULT_SNMP_PORT);
         Notification notification = getAlertNotification(true);
         notification.Callback = mock(DispatchCallback.class);
-        notification.CallbackIds = new ArrayList<>();
+        notification.CallbackIds = mock(List.class);
         Map<String, String> properties = new HashMap<>();
         properties.put(AmbariSNMPDispatcher.PORT_PROPERTY, "3");
         properties.put(AmbariSNMPDispatcher.COMMUNITY_PROPERTY, "4");
@@ -137,7 +138,7 @@ public class AmbariSNMPDispatcherTest {
         AmbariSNMPDispatcher dispatcher = new AmbariSNMPDispatcher(DEFAULT_SNMP_PORT);
         Notification notification = getAlertNotification(true);
         notification.Callback = mock(DispatchCallback.class);
-        notification.CallbackIds = new ArrayList<>();
+        notification.CallbackIds = mock(List.class);
         Map<String, String> properties = new HashMap<>();
         properties.put(AmbariSNMPDispatcher.PORT_PROPERTY, "3");
         properties.put(AmbariSNMPDispatcher.COMMUNITY_PROPERTY, "4");
@@ -209,7 +210,7 @@ public class AmbariSNMPDispatcherTest {
         AmbariSNMPDispatcher.SnmpVersion snmpVersion = AmbariSNMPDispatcher.SnmpVersion.SNMPv2c;
         Notification notification = mock(AlertNotification.class);
         notification.Callback = mock(DispatchCallback.class);
-        notification.CallbackIds = new ArrayList<>();
+        notification.CallbackIds = mock(List.class);
         Map<String, String> properties = new HashMap<>();
         properties.put(AmbariSNMPDispatcher.PORT_PROPERTY, "3");
         properties.put(AmbariSNMPDispatcher.COMMUNITY_PROPERTY, "4");
@@ -227,7 +228,7 @@ public class AmbariSNMPDispatcherTest {
         AmbariSNMPDispatcher dispatcher = new AmbariSNMPDispatcher(DEFAULT_SNMP_PORT);
         Notification notification = getAlertNotification(true);
         notification.Callback = mock(DispatchCallback.class);
-        notification.CallbackIds = new ArrayList<>();
+        notification.CallbackIds = mock(List.class);
         Map<String, String> properties = new HashMap<>();
         properties.put(AmbariSNMPDispatcher.PORT_PROPERTY, "162");
         properties.put(AmbariSNMPDispatcher.COMMUNITY_PROPERTY, "public");
@@ -256,7 +257,7 @@ public class AmbariSNMPDispatcherTest {
         for (VariableBinding variableBinding : pdu.toArray()) {
             variableBindings.put(variableBinding.getOid().toString(), variableBinding);
         }
-        assertEquals(10, variableBindings.size());
+    assertEquals(11, variableBindings.size());
         assertEquals(AmbariSNMPDispatcher.AMBARI_ALERT_TRAP_OID, variableBindings.get(SnmpConstants.snmpTrapOID.toString()).toValueString());
         assertTrue(variableBindings.get(SnmpConstants.snmpTrapOID.toString()).getVariable() instanceof OID);
         assertEquals(String.valueOf(DEFINITION_ID), variableBindings.get(AmbariSNMPDispatcher.AMBARI_ALERT_DEFINITION_ID_OID).toValueString());
@@ -288,7 +289,7 @@ public class AmbariSNMPDispatcherTest {
         for (VariableBinding variableBinding : pdu.toArray()) {
             variableBindings.put(variableBinding.getOid().toString(), variableBinding);
         }
-        assertEquals(10, variableBindings.size());
+    assertEquals(11, variableBindings.size());
         assertEquals("null", variableBindings.get(AmbariSNMPDispatcher.AMBARI_ALERT_COMPONENT_NAME_OID).toValueString());
     }
 
@@ -305,7 +306,7 @@ public class AmbariSNMPDispatcherTest {
             variableBindings.put(variableBinding.getOid().toString(), variableBinding);
         }
 
-        assertEquals(10, variableBindings.size());
+    assertEquals(11, variableBindings.size());
         assertEquals(AmbariSNMPDispatcher.AMBARI_ALERT_TRAP_OID, variableBindings.get(SnmpConstants.snmpTrapOID.toString()).toValueString());
         assertEquals(String.valueOf(DEFINITION_ID), variableBindings.get(AmbariSNMPDispatcher.AMBARI_ALERT_DEFINITION_ID_OID).toValueString());
         assertEquals(DEFINITION_NAME, variableBindings.get(AmbariSNMPDispatcher.AMBARI_ALERT_DEFINITION_NAME_OID).toValueString());

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa652afe/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
index 0bb118a..c86c51d 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
@@ -19,11 +19,15 @@ package org.apache.ambari.server.state.services;
 
 import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -36,27 +40,39 @@ import java.util.UUID;
 import java.util.Vector;
 import java.util.concurrent.Executor;
 
+import javax.persistence.EntityManager;
+
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.notifications.DispatchFactory;
 import org.apache.ambari.server.notifications.Notification;
 import org.apache.ambari.server.notifications.NotificationDispatcher;
 import org.apache.ambari.server.notifications.TargetConfigurationResult;
 import org.apache.ambari.server.notifications.dispatchers.AmbariSNMPDispatcher;
-import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
+import org.apache.ambari.server.orm.dao.AlertsDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
 import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.stack.StackManagerFactory;
 import org.apache.ambari.server.state.AlertState;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.NotificationState;
 import org.apache.ambari.server.state.alert.Scope;
 import org.apache.ambari.server.state.alert.SourceType;
 import org.apache.ambari.server.state.alert.TargetType;
+import org.apache.ambari.server.state.stack.OsFamily;
 import org.easymock.EasyMock;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 import org.snmp4j.CommandResponder;
 import org.snmp4j.CommandResponderEvent;
 import org.snmp4j.PDU;
@@ -68,6 +84,7 @@ import org.snmp4j.smi.GenericAddress;
 import org.snmp4j.smi.Integer32;
 import org.snmp4j.smi.OID;
 import org.snmp4j.smi.OctetString;
+import org.snmp4j.smi.TimeTicks;
 import org.snmp4j.smi.VariableBinding;
 import org.snmp4j.transport.DefaultUdpTransportMapping;
 
@@ -75,11 +92,12 @@ import com.google.inject.Binder;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Module;
-import com.google.inject.util.Modules;
 
 /**
  * Tests the {@link AlertNoticeDispatchService}.
  */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ AmbariSNMPDispatcher.class, ManagementFactory.class })
 public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
 
   final static String ALERT_NOTICE_UUID_1 = UUID.randomUUID().toString();
@@ -92,6 +110,7 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
   private DispatchFactory m_dispatchFactory = null;
   private AlertDispatchDAO m_dao = null;
   private Injector m_injector;
+  private RuntimeMXBean m_runtimeMXBean;
 
   List<AlertDefinitionEntity> m_definitions = new ArrayList<>();
   List<AlertHistoryEntity> m_histories = new ArrayList<>();
@@ -103,8 +122,7 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
     m_metaInfo = createNiceMock(AmbariMetaInfo.class);
 
     // create an injector which will inject the mocks
-    m_injector = Guice.createInjector(Modules.override(
-        new InMemoryDefaultTestModule()).with(new MockModule()));
+    m_injector = Guice.createInjector(new MockModule());
 
     Assert.assertNotNull(m_injector);
 
@@ -150,7 +168,17 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
         m_histories.add(history);
       }
     }
-  }
+
+    // mock out the uptime to be a while (since most tests are not testing
+    // system uptime)
+    m_runtimeMXBean = EasyMock.createNiceMock(RuntimeMXBean.class);
+    PowerMock.mockStatic(ManagementFactory.class);
+    expect(ManagementFactory.getRuntimeMXBean()).andReturn(m_runtimeMXBean).atLeastOnce();
+    PowerMock.replay(ManagementFactory.class);
+    expect(m_runtimeMXBean.getUptime()).andReturn(360000L).atLeastOnce();
+
+    replay( m_runtimeMXBean);
+    }
 
   /**
    * Tests the parsing of the {@link AlertHistoryEntity} list into
@@ -381,7 +409,8 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
 
     List<Vector> expectedTrapVectors = new LinkedList<>();
     Vector firstVector = new Vector();
-    firstVector.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(AmbariSNMPDispatcher.AMBARI_ALERT_TRAP_OID)));
+    firstVector.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(360000L)));
+    firstVector.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(AmbariSNMPDispatcher.AMBARI_ALERT_TRAP_OID)));    
     firstVector.add(new VariableBinding(new OID(AmbariSNMPDispatcher.AMBARI_ALERT_DEFINITION_ID_OID), new Integer32(new BigDecimal(1L).intValueExact())));
     firstVector.add(new VariableBinding(new OID(AmbariSNMPDispatcher.AMBARI_ALERT_DEFINITION_NAME_OID), new OctetString("alert-definition-1")));
     firstVector.add(new VariableBinding(new OID(AmbariSNMPDispatcher.AMBARI_ALERT_DEFINITION_HASH_OID), new OctetString("1")));
@@ -762,9 +791,20 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
      */
     @Override
     public void configure(Binder binder) {
+      Cluster cluster = EasyMock.createNiceMock(Cluster.class);
       binder.bind(AlertDispatchDAO.class).toInstance(m_dao);
       binder.bind(DispatchFactory.class).toInstance(m_dispatchFactory);
+      binder.bind(StackManagerFactory.class).toInstance(createNiceMock(StackManagerFactory.class));
       binder.bind(AmbariMetaInfo.class).toInstance(m_metaInfo);
+      binder.bind(Clusters.class).toInstance(createNiceMock(Clusters.class));
+      binder.bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
+      binder.bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+      binder.bind(Cluster.class).toInstance(cluster);
+      binder.bind(AlertDefinitionDAO.class).toInstance(createNiceMock(AlertDefinitionDAO.class));
+      binder.bind(AlertsDAO.class).toInstance(createNiceMock(AlertsDAO.class));
+      binder.bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+
+      binder.bind(AlertNoticeDispatchService.class).toInstance(new AlertNoticeDispatchService());
 
       EasyMock.expect(m_metaInfo.getServerVersion()).andReturn("2.0.0").anyTimes();
       EasyMock.replay(m_metaInfo);
@@ -782,6 +822,7 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
       receivedTrapsVectors = new LinkedList<>();
 
       CommandResponder trapPrinter = new CommandResponder() {
+        @Override
         public synchronized void processPdu(CommandResponderEvent e){
           PDU command = e.getPDU();
           if (command != null) {


[25/50] [abbrv] ambari git commit: AMBARI-22458 - SNMP Trap should contain sysuptime field filled (Amarnathreddy Pappu via jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22458 - SNMP Trap should contain sysuptime field filled (Amarnathreddy Pappu via jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/73d99d8c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/73d99d8c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/73d99d8c

Branch: refs/heads/branch-3.0-perf
Commit: 73d99d8c3f7f0067f06b1a0c04eccbcf9554c0bd
Parents: 3fa1289
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Tue Nov 28 10:29:59 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue Nov 28 10:30:41 2017 -0500

----------------------------------------------------------------------
 .../notifications/dispatchers/AmbariSNMPDispatcher.java  | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/73d99d8c/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
index 596079b..8e397ed 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
@@ -38,9 +38,13 @@ import org.snmp4j.smi.OID;
 import org.snmp4j.smi.OctetString;
 import org.snmp4j.smi.VariableBinding;
 import org.snmp4j.util.DefaultPDUFactory;
+import org.snmp4j.smi.TimeTicks;
 
 import com.google.inject.Singleton;
 
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ManagementFactory;
+
 /**
  * The {@link AmbariSNMPDispatcher} class is used to dispatch {@link AlertNotification} via SNMP using predefined Ambari OIDs.
  *
@@ -113,7 +117,12 @@ public class AmbariSNMPDispatcher extends SNMPDispatcher {
         }
 
         pdu.setType(snmpVersion.getTrapType());
-        // Set trap oid for PDU
+    
+        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
+        long uptimeInMillis = runtimeMXBean.getUptime();
+        pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(uptimeInMillis)));
+
+       // Set trap oid for PDU
         pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(AMBARI_ALERT_TRAP_OID)));
         // Set notification body and subject for PDU objects with identifiers specified in dispatch properties.
         AlertNoticeDispatchService.AlertInfo alertInfo = alertNotification.getAlertInfo();


[22/50] [abbrv] ambari git commit: AMBARI-22514. Initial implementation of Schedulable document deletion & archiving for Infra Solr (Krisztian Kasa via oleewere)

Posted by ao...@apache.org.
AMBARI-22514. Initial implementation of Schedulable document deletion & archiving for Infra Solr (Krisztian Kasa via oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/393fdb80
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/393fdb80
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/393fdb80

Branch: refs/heads/branch-3.0-perf
Commit: 393fdb8048ff579e8a55cd1b477a23d1bf105576
Parents: 2bf3c8e
Author: Krisztian Kasa <ka...@gmail.com>
Authored: Tue Nov 28 15:45:22 2017 +0100
Committer: Oliver Szabo <ol...@gmail.com>
Committed: Tue Nov 28 15:47:59 2017 +0100

----------------------------------------------------------------------
 ambari-infra/ambari-infra-manager/pom.xml       |  11 ++
 .../infra/job/archive/CompositeFileAction.java  |  46 +++++
 .../ambari/infra/job/archive/Document.java      |  54 +++++
 .../infra/job/archive/DocumentDestination.java  |  23 +++
 .../archive/DocumentExportConfiguration.java    | 118 +++++++++++
 .../job/archive/DocumentExportJobListener.java  |  35 ++++
 .../job/archive/DocumentExportProperties.java   | 112 +++++++++++
 .../job/archive/DocumentExportStepListener.java |  47 +++++
 .../infra/job/archive/DocumentExporter.java     |  99 ++++++++++
 .../infra/job/archive/DocumentItemReader.java   | 135 +++++++++++++
 .../infra/job/archive/DocumentItemWriter.java   |  25 +++
 .../infra/job/archive/DocumentIterator.java     |  25 +++
 .../infra/job/archive/DocumentSource.java       |  24 +++
 .../ambari/infra/job/archive/FileAction.java    |  25 +++
 .../job/archive/LocalDocumentItemWriter.java    |  72 +++++++
 .../ambari/infra/job/archive/S3Properties.java  |  64 ++++++
 .../ambari/infra/job/archive/S3Uploader.java    |  51 +++++
 .../infra/job/archive/SolrDocumentIterator.java |  90 +++++++++
 .../infra/job/archive/SolrDocumentSource.java   |  68 +++++++
 .../infra/job/archive/SolrQueryBuilder.java     | 115 +++++++++++
 .../infra/job/archive/SolrQueryProperties.java  |  69 +++++++
 .../infra/job/archive/TarGzCompressor.java      |  50 +++++
 .../apache/ambari/infra/manager/JobManager.java |  21 +-
 .../src/main/resources/infra-manager.properties |  12 ++
 .../src/main/resources/log4j2.xml               |   2 +-
 .../infra/job/archive/DocumentExporterTest.java | 147 ++++++++++++++
 .../job/archive/DocumentItemReaderTest.java     | 197 +++++++++++++++++++
 .../archive/LocalDocumentItemWriterTest.java    |  98 +++++++++
 .../infra/job/archive/SolrQueryBuilderTest.java | 113 +++++++++++
 .../test-config/logfeeder/logfeeder.properties  |   2 +-
 30 files changed, 1940 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/pom.xml b/ambari-infra/ambari-infra-manager/pom.xml
index aa86da8..67bf7d1 100644
--- a/ambari-infra/ambari-infra-manager/pom.xml
+++ b/ambari-infra/ambari-infra-manager/pom.xml
@@ -141,6 +141,12 @@
       <version>3.4</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-all</artifactId>
+      <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
     <!-- Spring dependencies -->
     <dependency>
       <groupId>org.springframework</groupId>
@@ -417,6 +423,11 @@
       <groupId>com.google.guava</groupId>
       <version>20.0</version>
     </dependency>
+    <dependency>
+      <groupId>com.amazonaws</groupId>
+      <artifactId>aws-java-sdk-s3</artifactId>
+      <version>1.11.5</version>
+    </dependency>
   </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/CompositeFileAction.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/CompositeFileAction.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/CompositeFileAction.java
new file mode 100644
index 0000000..84ce160
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/CompositeFileAction.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import java.io.File;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+public class CompositeFileAction implements FileAction {
+
+  private final List<FileAction> actions;
+
+  public CompositeFileAction(FileAction... actions) {
+    this.actions = asList(actions);
+  }
+
+  public void add(FileAction action) {
+    actions.add(action);
+  }
+
+  @Override
+  public File perform(File inputFile) {
+    File file = inputFile;
+    for (FileAction action : actions) {
+      file = action.perform(file);
+    }
+    return file;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/Document.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/Document.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/Document.java
new file mode 100644
index 0000000..84f5ece
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/Document.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Collections.unmodifiableMap;
+
+// TODO: create entities for each solr collections
+public class Document {
+  private final Map<String, String> fieldMap;
+
+  private Document() {
+    fieldMap = new HashMap<>();
+  }
+
+  public Document(Map<String, String> fieldMap) {
+    this.fieldMap = unmodifiableMap(fieldMap);
+  }
+
+  public String get(String key) {
+    return fieldMap.get(key);
+  }
+
+  @JsonAnyGetter
+  private Map<String, String> getFieldMap() {
+    return fieldMap;
+  }
+
+  @JsonAnySetter
+  private void put(String key, String value) {
+    fieldMap.put(key, value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentDestination.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentDestination.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentDestination.java
new file mode 100644
index 0000000..f647a36
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentDestination.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+public interface DocumentDestination {
+  DocumentItemWriter open(Document firstDocument);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportConfiguration.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportConfiguration.java
new file mode 100644
index 0000000..69f41d3
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportConfiguration.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.JobScope;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.StepScope;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.inject.Inject;
+import java.io.File;
+import java.nio.file.Paths;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+import static org.apache.ambari.infra.job.archive.SolrDocumentSource.SOLR_DATETIME_FORMATTER;
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+@Configuration
+public class DocumentExportConfiguration {
+  private static final Logger LOG = LoggerFactory.getLogger(DocumentExportConfiguration.class);
+  private static final DateTimeFormatter FILENAME_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH_mm_ss.SSSX");
+
+  @Inject
+  private DocumentExportProperties properties;
+
+  @Inject
+  private StepBuilderFactory steps;
+
+  @Inject
+  private JobBuilderFactory jobs;
+
+
+
+  @Bean
+  public Job logExportJob(@Qualifier("exportStep") Step logExportStep) {
+    return jobs.get("solr_data_export").listener(new DocumentExportJobListener()).start(logExportStep).build();
+  }
+
+  @Bean
+  @JobScope
+  public Step exportStep(DocumentExporter documentExporter) {
+    return steps.get("export")
+            .tasklet(documentExporter)
+            .listener(new DocumentExportStepListener(properties))
+            .build();
+  }
+
+  @Bean
+  @StepScope
+  public DocumentExporter getDocumentExporter(DocumentItemReader documentItemReader,
+                                              @Value("#{stepExecution.jobExecution.id}") String jobId) {
+    File path = Paths.get(
+            properties.getDestinationDirectoryPath(),
+            String.format("%s_%s", properties.getQuery().getCollection(), jobId)).toFile(); // TODO: add end date
+    LOG.info("Destination directory path={}", path);
+    if (!path.exists()) {
+      if (!path.mkdirs()) {
+        LOG.warn("Unable to create directory {}", path);
+      }
+    }
+
+    CompositeFileAction fileAction = new CompositeFileAction(new TarGzCompressor());
+
+    return new DocumentExporter(
+            documentItemReader,
+            firstDocument -> new LocalDocumentItemWriter(
+                    new File(path, String.format("%s_-_%s.json",
+                            properties.getQuery().getCollection(),
+                            firstDocument.get(properties.getFileNameSuffixColumn()))),
+                    fileAction),
+            properties.getWriteBlockSize());
+  }
+
+  @Bean
+  @StepScope
+  public DocumentItemReader reader(DocumentSource documentSource) {
+    return new DocumentItemReader(documentSource, properties.getReadBlockSize());
+  }
+
+  @Bean
+  @StepScope
+  public DocumentSource logSource(@Value("#{jobParameters[endDate]}") String endDateText) {
+    OffsetDateTime endDate = OffsetDateTime.now(ZoneOffset.UTC);
+    if (!isBlank(endDateText))
+      endDate = OffsetDateTime.parse(endDateText);
+
+    return new SolrDocumentSource(
+            properties.getZooKeeperSocket(),
+            properties.getQuery(),
+            SOLR_DATETIME_FORMATTER.format(endDate));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportJobListener.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportJobListener.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportJobListener.java
new file mode 100644
index 0000000..f1df46c
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportJobListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobExecutionListener;
+
+public class DocumentExportJobListener implements JobExecutionListener {
+  @Override
+  public void beforeJob(JobExecution jobExecution) {
+
+  }
+
+  @Override
+  public void afterJob(JobExecution jobExecution) {
+    jobExecution.setExitStatus(new ExitStatus(ExitStatus.COMPLETED.getExitCode()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportProperties.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportProperties.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportProperties.java
new file mode 100644
index 0000000..d6301c0
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportProperties.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.hibernate.validator.constraints.NotBlank;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+import javax.validation.constraints.Min;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+@Configuration
+@PropertySource(value = {"classpath:infra-manager.properties"})
+@ConfigurationProperties(prefix = "infra-manager.jobs.solr_data_export")
+public class DocumentExportProperties {
+  @NotBlank
+  private String zooKeeperSocket;
+  @Min(1)
+  private int readBlockSize;
+  @Min(1)
+  private int writeBlockSize;
+  @NotBlank
+  private String destinationDirectoryPath;
+  @NotBlank
+  private String fileNameSuffixColumn;
+  private SolrQueryProperties query;
+
+  public String getZooKeeperSocket() {
+    return zooKeeperSocket;
+  }
+
+  public void setZooKeeperSocket(String zooKeeperSocket) {
+    this.zooKeeperSocket = zooKeeperSocket;
+  }
+
+  public int getReadBlockSize() {
+    return readBlockSize;
+  }
+
+  public void setReadBlockSize(int readBlockSize) {
+    this.readBlockSize = readBlockSize;
+  }
+
+  public int getWriteBlockSize() {
+    return writeBlockSize;
+  }
+
+  public void setWriteBlockSize(int writeBlockSize) {
+    this.writeBlockSize = writeBlockSize;
+  }
+
+  public String getDestinationDirectoryPath() {
+    return destinationDirectoryPath;
+  }
+
+  public void setDestinationDirectoryPath(String destinationDirectoryPath) {
+    this.destinationDirectoryPath = destinationDirectoryPath;
+  }
+
+  public void apply(JobParameters jobParameters) {
+    // TODO: solr query params
+    zooKeeperSocket = jobParameters.getString("zooKeeperSocket", zooKeeperSocket);
+    readBlockSize = getIntJobParameter(jobParameters, "readBlockSize", readBlockSize);
+    writeBlockSize = getIntJobParameter(jobParameters, "writeBlockSize", writeBlockSize);
+    destinationDirectoryPath = jobParameters.getString("destinationDirectoryPath", destinationDirectoryPath);
+    query.setCollection(jobParameters.getString("collection", query.getCollection()));
+    query.setQueryText(jobParameters.getString("queryText", query.getQueryText()));
+    query.setFilterQueryText(jobParameters.getString("filterQueryText", query.getFilterQueryText()));
+  }
+
+  private int getIntJobParameter(JobParameters jobParameters, String parameterName, int defaultValue) {
+    String writeBlockSizeText = jobParameters.getString(parameterName);
+    if (isBlank(writeBlockSizeText))
+      return defaultValue;
+    return this.writeBlockSize = Integer.parseInt(writeBlockSizeText);
+  }
+
+  public String getFileNameSuffixColumn() {
+    return fileNameSuffixColumn;
+  }
+
+  public void setFileNameSuffixColumn(String fileNameSuffixColumn) {
+    this.fileNameSuffixColumn = fileNameSuffixColumn;
+  }
+
+  public SolrQueryProperties getQuery() {
+    return query;
+  }
+
+  public void setQuery(SolrQueryProperties query) {
+    this.query = query;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportStepListener.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportStepListener.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportStepListener.java
new file mode 100644
index 0000000..3bab6d5
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExportStepListener.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.StepExecutionListener;
+
+public class DocumentExportStepListener implements StepExecutionListener {
+  private static final Logger LOG = LoggerFactory.getLogger(DocumentExportStepListener.class);
+
+  private final DocumentExportProperties properties;
+
+  public DocumentExportStepListener(DocumentExportProperties properties) {
+    this.properties = properties;
+  }
+
+  @Override
+  public void beforeStep(StepExecution stepExecution) {
+    properties.apply(stepExecution.getJobParameters());
+    LOG.info("LogExport step - before step execution");
+  }
+
+  @Override
+  public ExitStatus afterStep(StepExecution stepExecution) {
+    LOG.info("LogExport step - after step execution");
+    return stepExecution.getExitStatus();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
new file mode 100644
index 0000000..6106c20
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.StepContribution;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.StepExecutionListener;
+import org.springframework.batch.core.scope.context.ChunkContext;
+import org.springframework.batch.core.step.tasklet.Tasklet;
+import org.springframework.batch.item.ExecutionContext;
+import org.springframework.batch.item.ItemStreamReader;
+import org.springframework.batch.repeat.RepeatStatus;
+
+public class DocumentExporter implements Tasklet, StepExecutionListener {
+
+  private boolean complete = false;
+  private final ItemStreamReader<Document> documentReader;
+  private final DocumentDestination documentDestination;
+  private final int writeBlockSize;
+
+  public DocumentExporter(ItemStreamReader<Document> documentReader, DocumentDestination documentDestination, int writeBlockSize) {
+    this.documentReader = documentReader;
+    this.documentDestination = documentDestination;
+    this.writeBlockSize = writeBlockSize;
+  }
+
+  @Override
+  public void beforeStep(StepExecution stepExecution) {
+
+  }
+
+  @Override
+  public ExitStatus afterStep(StepExecution stepExecution) {
+    if (complete) {
+      return ExitStatus.COMPLETED;
+    }
+		else {
+      return ExitStatus.FAILED;
+    }
+  }
+
+  @Override
+  public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
+    ExecutionContext executionContext = chunkContext.getStepContext().getStepExecution().getExecutionContext();
+    documentReader.open(executionContext);
+
+    DocumentItemWriter writer = null;
+    int writtenCount = 0;
+    try {
+      Document document;
+      while ((document = documentReader.read()) != null) {
+        if (writer != null && writtenCount >= writeBlockSize) {
+          writer.close();
+          writer = null;
+          writtenCount = 0;
+          documentReader.update(executionContext);
+        }
+
+        if (writer == null)
+          writer = documentDestination.open(document);
+
+        writer.write(document);
+        ++writtenCount;
+      }
+    }
+    catch (Exception e) {
+      if (writer != null) {
+        writer.revert();
+        writer = null;
+      }
+      throw e;
+    }
+    finally {
+      if (writer != null)
+        writer.close();
+      documentReader.close();
+    }
+
+    complete = true;
+    return RepeatStatus.FINISHED;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemReader.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemReader.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemReader.java
new file mode 100644
index 0000000..a4378a4
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemReader.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.springframework.batch.item.ExecutionContext;
+import org.springframework.batch.item.ItemStreamException;
+import org.springframework.batch.item.support.AbstractItemStreamItemReader;
+import org.springframework.batch.repeat.CompletionPolicy;
+import org.springframework.batch.repeat.RepeatContext;
+import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.batch.repeat.context.RepeatContextSupport;
+import org.springframework.util.ClassUtils;
+
+public class DocumentItemReader extends AbstractItemStreamItemReader<Document> implements CompletionPolicy {
+
+  public final static String POSITION = "last-read";
+
+  private final DocumentSource documentSource;
+  private final int readBlockSize;
+
+  private DocumentIterator documentIterator = null;
+  private int count = 0;
+  private boolean eof = false;
+  private Document current = null;
+  private Document previous = null;
+
+  public DocumentItemReader(DocumentSource documentSource, int readBlockSize) {
+    this.documentSource = documentSource;
+    this.readBlockSize = readBlockSize;
+    setName(ClassUtils.getShortName(DocumentItemReader.class));
+  }
+
+  @Override
+  public Document read() throws Exception {
+    if (documentIterator == null)
+      openStream();
+    Document next = getNext();
+    if (next == null && count > readBlockSize) {
+      openStream();
+      next = getNext();
+    }
+    eof = next == null;
+    if (eof && documentIterator != null)
+      documentIterator.close();
+
+    previous = current;
+    current = next;
+    return current;
+  }
+
+  private Document getNext() {
+    ++count;
+    return documentIterator.next();
+  }
+
+  private void openStream() {
+    closeStream();
+    documentIterator = documentSource.open(current, readBlockSize);
+    count = 0;
+  }
+
+  private void closeStream() {
+    if (documentIterator == null)
+      return;
+    try {
+      documentIterator.close();
+    }
+    catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+    documentIterator = null;
+  }
+
+  @Override
+  public void open(ExecutionContext executionContext) {
+    super.open(executionContext);
+    current = null;
+    previous = null;
+    eof = false;
+    documentIterator = null;
+    if (!executionContext.containsKey(POSITION))
+      return;
+
+    current = (Document) executionContext.get(POSITION);
+  }
+
+  @Override
+  public void update(ExecutionContext executionContext) throws ItemStreamException {
+    super.update(executionContext);
+    if (previous != null)
+      executionContext.put(POSITION, previous);
+  }
+
+  @Override
+  public void close() {
+    closeStream();
+  }
+
+  @Override
+  public boolean isComplete(RepeatContext context, RepeatStatus result) {
+    return eof;
+  }
+
+  @Override
+  public boolean isComplete(RepeatContext context) {
+    return eof;
+  }
+
+  @Override
+  public RepeatContext start(RepeatContext parent) {
+    return new RepeatContextSupport(parent);
+  }
+
+  @Override
+  public void update(RepeatContext context) {
+    if (eof)
+      context.setCompleteOnly();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemWriter.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemWriter.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemWriter.java
new file mode 100644
index 0000000..e96f6f1
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentItemWriter.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+public interface DocumentItemWriter {
+  void write(Document document);
+  void revert();
+  void close();
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentIterator.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentIterator.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentIterator.java
new file mode 100644
index 0000000..6232cfc
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentIterator.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import java.util.Iterator;
+
+// TODO: generic closeable iterator
+public interface DocumentIterator extends Iterator<Document>, AutoCloseable {
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentSource.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentSource.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentSource.java
new file mode 100644
index 0000000..c9871a3
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentSource.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+// TODO: generic object source
+public interface DocumentSource {
+  DocumentIterator open(Document current, int rows);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/FileAction.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/FileAction.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/FileAction.java
new file mode 100644
index 0000000..26a8c63
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/FileAction.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import java.io.File;
+
+public interface FileAction {
+  File perform(File inputFile);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriter.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriter.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriter.java
new file mode 100644
index 0000000..02d898d
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriter.java
@@ -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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.IOUtils;
+
+import java.io.*;
+
+public class LocalDocumentItemWriter implements DocumentItemWriter {
+  private static final ObjectMapper json = new ObjectMapper();
+  private static final String ENCODING = "UTF-8";
+
+  private final File outFile;
+  private final BufferedWriter bufferedWriter;
+  private final FileAction fileAction;
+
+  public LocalDocumentItemWriter(File outFile, FileAction fileAction) {
+    this.fileAction = fileAction;
+    this.outFile = outFile;
+    try {
+      this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), ENCODING));
+    } catch (UnsupportedEncodingException e) {
+      throw new RuntimeException(e);
+    } catch (FileNotFoundException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  @Override
+  public void write(Document document) {
+    try {
+      bufferedWriter.write(json.writeValueAsString(document));
+      bufferedWriter.newLine();
+    }
+    catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  @Override
+  public void revert() {
+    IOUtils.closeQuietly(bufferedWriter);
+    outFile.delete();
+  }
+
+  @Override
+  public void close() {
+    try {
+      bufferedWriter.close();
+      fileAction.perform(outFile);
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Properties.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Properties.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Properties.java
new file mode 100644
index 0000000..495401d
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Properties.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.hibernate.validator.constraints.NotBlank;
+
+public class S3Properties {
+  @NotBlank
+  private String accessKey;
+  @NotBlank
+  private String secretKey;
+  @NotBlank
+  private String keyPrefix;
+  @NotBlank
+  private String bucketName;
+
+  public String getAccessKey() {
+    return accessKey;
+  }
+
+  public String getSecretKey() {
+    return secretKey;
+  }
+
+  public String getKeyPrefix() {
+    return keyPrefix;
+  }
+
+  public String getBucketName() {
+    return bucketName;
+  }
+
+  public void setAccessKey(String accessKey) {
+    this.accessKey = accessKey;
+  }
+
+  public void setSecretKey(String secretKey) {
+    this.secretKey = secretKey;
+  }
+
+  public void setKeyPrefix(String keyPrefix) {
+    this.keyPrefix = keyPrefix;
+  }
+
+  public void setBucketName(String bucketName) {
+    this.bucketName = bucketName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Uploader.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Uploader.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Uploader.java
new file mode 100644
index 0000000..3214e50
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/S3Uploader.java
@@ -0,0 +1,51 @@
+package org.apache.ambari.infra.job.archive;
+
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.services.s3.AmazonS3Client;
+
+import java.io.File;
+
+/*
+ * 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.
+ */
+public class S3Uploader implements FileAction {
+
+  private final AmazonS3Client client;
+  private final String keyPrefix;
+  private final String bucketName;
+
+  public S3Uploader(S3Properties s3Properties) {
+    this.keyPrefix = s3Properties.getKeyPrefix();
+    this.bucketName = s3Properties.getBucketName();
+    BasicAWSCredentials credentials = new BasicAWSCredentials(s3Properties.getAccessKey(), s3Properties.getSecretKey());
+    client = new AmazonS3Client(credentials);
+  }
+
+  @Override
+  public File perform(File inputFile) {
+    String key = keyPrefix + inputFile.getName();
+
+    if (client.doesObjectExist(bucketName, key)) {
+      System.out.println("Object '" + key + "' already exists");
+      System.exit(0);
+    }
+
+    client.putObject(bucketName, key, inputFile);
+    return inputFile;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentIterator.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentIterator.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentIterator.java
new file mode 100644
index 0000000..db4069b
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentIterator.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrDocument;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TimeZone;
+
+public class SolrDocumentIterator implements DocumentIterator {
+
+  private static final DateFormat SOLR_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+
+  static {
+    SOLR_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+
+  private final Iterator<SolrDocument> documentIterator;
+  private final CloudSolrClient client;
+
+
+  public SolrDocumentIterator(QueryResponse response, CloudSolrClient client) {
+    documentIterator = response.getResults().iterator();
+    this.client = client;
+  }
+
+  @Override
+  public Document next() {
+    if (!documentIterator.hasNext())
+      return null;
+    
+    SolrDocument document = documentIterator.next();
+    HashMap<String, String> fieldMap = new HashMap<>();
+    for (String key : document.getFieldNames()) {
+      fieldMap.put(key, toString(document.get(key)));
+    }
+
+    return new Document(fieldMap);
+  }
+
+  private String toString(Object value) {
+    if (value == null) {
+      return null;
+    }
+    else if (value instanceof Date) {
+      return SOLR_DATE_FORMAT.format(value);
+    }
+    else {
+      return value.toString();
+    }
+  }
+
+  @Override
+  public void close() {
+    try {
+      client.close();
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+
+  @Override
+  public boolean hasNext() {
+    return documentIterator.hasNext();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentSource.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentSource.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentSource.java
new file mode 100644
index 0000000..2181ba3
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrDocumentSource.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.time.format.DateTimeFormatter;
+
+public class SolrDocumentSource implements DocumentSource {
+  public static final DateTimeFormatter SOLR_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+  private static final Logger LOG = LoggerFactory.getLogger(SolrDocumentSource.class);
+
+  private final String zkHost;
+  private final SolrQueryProperties properties;
+  private final String endValue;
+
+  public SolrDocumentSource(String zkHost, SolrQueryProperties properties, String endValue) {
+    this.zkHost = zkHost;
+    this.properties = properties;
+    this.endValue = endValue;
+  }
+
+  @Override
+  public DocumentIterator open(Document current, int rows) {
+    CloudSolrClient client = new CloudSolrClient.Builder().withZkHost(zkHost).build();
+    client.setDefaultCollection(properties.getCollection());
+
+    SolrQuery query = properties.toQueryBuilder()
+            .setEndValue(endValue)
+            .setDocument(current)
+            .build();
+    query.setRows(rows);
+
+    LOG.info("Executing solr query {}", query.toLocalParamsString());
+
+    try {
+      QueryResponse response = client.query(query);
+      return new SolrDocumentIterator(response, client);
+    } catch (SolrServerException e) {
+      throw new RuntimeException(e);
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryBuilder.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryBuilder.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryBuilder.java
new file mode 100644
index 0000000..d0f6d40
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryBuilder.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.apache.solr.client.solrj.SolrQuery;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.apache.solr.client.solrj.SolrQuery.ORDER.asc;
+
+public class SolrQueryBuilder {
+
+  public static final Pattern PARAMETER_PATTERN = Pattern.compile("\\$\\{[a-z]+\\}");
+
+  private String queryText;
+  private String endValue;
+  private String filterQueryText;
+  private Document document;
+  private String[] sortFields;
+
+  public SolrQueryBuilder() {
+    this.queryText = "*:*";
+  }
+
+  public SolrQueryBuilder setQueryText(String queryText) {
+    this.queryText = queryText;
+    return this;
+  }
+
+  public SolrQueryBuilder setEndValue(String endValue) {
+    this.endValue = endValue;
+    return this;
+  }
+
+  public SolrQueryBuilder setFilterQueryText(String filterQueryText) {
+    this.filterQueryText = filterQueryText;
+    return this;
+  }
+
+
+  public SolrQueryBuilder setDocument(Document document) {
+    this.document = document;
+    return this;
+  }
+
+  public SolrQueryBuilder addSort(String... sortBy) {
+    this.sortFields = sortBy;
+    return this;
+  }
+
+  public SolrQuery build() {
+    SolrQuery solrQuery = new SolrQuery();
+
+    String query = queryText;
+    query = setEndValueOn(query);
+
+    solrQuery.setQuery(query);
+
+    if (filterQueryText != null) {
+      String filterQuery = filterQueryText;
+      filterQuery = setEndValueOn(filterQuery);
+
+      Set<String> paramNames = collectParamNames(filterQuery);
+      if (document != null) {
+        for (String parameter : paramNames) {
+          if (document.get(parameter) != null)
+            filterQuery = filterQuery.replace(String.format("${%s}", parameter), document.get(parameter));
+        }
+      }
+
+      if (document == null && paramNames.isEmpty() || document != null && !paramNames.isEmpty())
+        solrQuery.setFilterQueries(filterQuery);
+    }
+
+    if (sortFields != null) {
+      for (String field : sortFields)
+        solrQuery.addSort(field, asc);
+    }
+
+    return solrQuery;
+  }
+
+  private String setEndValueOn(String query) {
+    if (endValue != null)
+      query = query.replace("${end}", endValue);
+    return query;
+  }
+
+  private Set<String> collectParamNames(String filterQuery) {
+    Matcher matcher = PARAMETER_PATTERN.matcher(filterQuery);
+    Set<String> parameters = new HashSet<>();
+    while (matcher.find())
+      parameters.add(matcher.group().replace("${", "").replace("}", ""));
+    return parameters;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryProperties.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryProperties.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryProperties.java
new file mode 100644
index 0000000..444a15b
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/SolrQueryProperties.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.hibernate.validator.constraints.NotBlank;
+
+public class SolrQueryProperties {
+  @NotBlank
+  private String collection;
+  @NotBlank
+  private String queryText;
+  private String filterQueryText;
+  private String[] sort;
+
+  public String getCollection() {
+    return collection;
+  }
+
+  public void setCollection(String collection) {
+    this.collection = collection;
+  }
+
+  public String getQueryText() {
+    return queryText;
+  }
+
+  public void setQueryText(String queryText) {
+    this.queryText = queryText;
+  }
+
+  public String getFilterQueryText() {
+    return filterQueryText;
+  }
+
+  public void setFilterQueryText(String filterQueryText) {
+    this.filterQueryText = filterQueryText;
+  }
+
+  public String[] getSort() {
+    return sort;
+  }
+
+  public void setSort(String[] sort) {
+    this.sort = sort;
+  }
+
+  public SolrQueryBuilder toQueryBuilder() {
+    return new SolrQueryBuilder().
+            setQueryText(queryText)
+            .setFilterQueryText(filterQueryText)
+            .addSort(sort);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/TarGzCompressor.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/TarGzCompressor.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/TarGzCompressor.java
new file mode 100644
index 0000000..8e34ca9
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/TarGzCompressor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
+import org.apache.commons.io.IOUtils;
+
+import java.io.*;
+
+public class TarGzCompressor implements FileAction {
+  @Override
+  public File perform(File inputFile) {
+    File tarGzFile = new File(inputFile.getParent(), inputFile.getName() + ".tar.gz");
+    try (TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(
+            new GzipCompressorOutputStream(new FileOutputStream(tarGzFile)))) {
+      TarArchiveEntry archiveEntry = new TarArchiveEntry(inputFile.getName());
+      archiveEntry.setSize(inputFile.length());
+      tarArchiveOutputStream.putArchiveEntry(archiveEntry);
+
+      try (FileInputStream fileInputStream = new FileInputStream(inputFile)) {
+        IOUtils.copy(fileInputStream, tarArchiveOutputStream);
+      }
+
+      tarArchiveOutputStream.closeArchiveEntry();
+    }
+    catch (IOException ex) {
+      throw new UncheckedIOException(ex);
+    }
+
+    return tarGzFile;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
index fc0a4f7..862119a 100644
--- a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
@@ -18,6 +18,7 @@
  */
 package org.apache.ambari.infra.manager;
 
+import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
 import org.apache.ambari.infra.model.ExecutionContextResponse;
 import org.apache.ambari.infra.model.JobDetailsResponse;
@@ -28,16 +29,14 @@ import org.apache.ambari.infra.model.JobOperationParams;
 import org.apache.ambari.infra.model.StepExecutionContextResponse;
 import org.apache.ambari.infra.model.StepExecutionInfoResponse;
 import org.apache.ambari.infra.model.StepExecutionProgressResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.batch.admin.history.StepExecutionHistory;
 import org.springframework.batch.admin.service.JobService;
 import org.springframework.batch.admin.service.NoSuchStepExecutionException;
 import org.springframework.batch.admin.web.JobInfo;
 import org.springframework.batch.admin.web.StepExecutionProgress;
-import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.JobInstance;
-import org.springframework.batch.core.JobParametersBuilder;
-import org.springframework.batch.core.JobParametersInvalidException;
-import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.*;
 import org.springframework.batch.core.launch.JobExecutionNotRunningException;
 import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException;
 import org.springframework.batch.core.launch.JobOperator;
@@ -54,7 +53,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -64,6 +62,8 @@ import java.util.TimeZone;
 @Named
 public class JobManager {
 
+  private static final Logger LOG = LoggerFactory.getLogger(JobManager.class);
+
   @Inject
   private JobService jobService;
 
@@ -83,9 +83,14 @@ public class JobManager {
   public JobExecutionInfoResponse launchJob(String jobName, String params)
     throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException,
     JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
-    // TODO: handle params
     JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
-    jobParametersBuilder.addDate("date", new Date());
+    if (params != null) {
+      LOG.info("Parsing parameters of job {} '{}'", jobName, params);
+      Splitter.on(',')
+              .trimResults()
+              .withKeyValueSeparator(Splitter.on('=').limit(2).trimResults())
+              .split(params).entrySet().forEach(entry -> jobParametersBuilder.addString(entry.getKey(), entry.getValue()));
+    }
     return new JobExecutionInfoResponse(jobService.launch(jobName, jobParametersBuilder.toJobParameters()), timeZone);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/resources/infra-manager.properties
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/resources/infra-manager.properties b/ambari-infra/ambari-infra-manager/src/main/resources/infra-manager.properties
index 8162376..7ef70aa 100644
--- a/ambari-infra/ambari-infra-manager/src/main/resources/infra-manager.properties
+++ b/ambari-infra/ambari-infra-manager/src/main/resources/infra-manager.properties
@@ -18,3 +18,15 @@ infra-manager.batch.db.username=admin
 infra-manager.batch.db.password=admin
 management.security.enabled=false
 management.health.solr.enabled=false
+infra-manager.server.data.folder=/tmp
+
+infra-manager.jobs.solr_data_export.zoo_keeper_socket=zookeeper:2181
+infra-manager.jobs.solr_data_export.read_block_size=100
+infra-manager.jobs.solr_data_export.write_block_size=150
+infra-manager.jobs.solr_data_export.file_name_suffix_column=logtime
+infra-manager.jobs.solr_data_export.destination_directory_path=/tmp/ambariInfraManager
+infra-manager.jobs.solr_data_export.query.collection=hadoop_logs
+infra-manager.jobs.solr_data_export.query.query_text=logtime:[* TO "${end}"]
+infra-manager.jobs.solr_data_export.query.filter_query_text=(logtime:"${logtime}" AND id:{"${id}" TO *]) OR logtime:{"${logtime}" TO "${end}"]
+infra-manager.jobs.solr_data_export.query.sort[0]=logtime
+infra-manager.jobs.solr_data_export.query.sort[1]=id

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/resources/log4j2.xml b/ambari-infra/ambari-infra-manager/src/main/resources/log4j2.xml
index ad1adcd..9737554 100644
--- a/ambari-infra/ambari-infra-manager/src/main/resources/log4j2.xml
+++ b/ambari-infra/ambari-infra-manager/src/main/resources/log4j2.xml
@@ -17,7 +17,7 @@
 -->
 <Configuration monitorinterval="30" status="info" strict="true">
   <Properties>
-    <Property name="logging.file">out/infra-manager.log</Property>
+    <Property name="logging.file">target/log/infra-manager.log</Property>
   </Properties>
   <Appenders>
     <Appender type="Console" name="Console">

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
new file mode 100644
index 0000000..88fbff0
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+package org.apache.ambari.infra.job.archive;
+
+import org.easymock.EasyMockRunner;
+import org.easymock.EasyMockSupport;
+import org.easymock.Mock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.scope.context.ChunkContext;
+import org.springframework.batch.core.scope.context.StepContext;
+import org.springframework.batch.item.ExecutionContext;
+import org.springframework.batch.item.ItemStreamReader;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.HashMap;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+
+@RunWith(EasyMockRunner.class)
+public class DocumentExporterTest extends EasyMockSupport {
+
+  private DocumentExporter documentExporter;
+  @Mock
+  private ItemStreamReader<Document> reader;
+  @Mock
+  private DocumentDestination documentDestination;
+  @Mock
+  private DocumentItemWriter documentItemWriter;
+  @Mock
+  private DocumentItemWriter documentItemWriter2;
+
+  private ExecutionContext executionContext;
+  private ChunkContext chunkContext;
+  private static final Document DOCUMENT = new Document(new HashMap<String, String>() {{ put("id", "1"); }});
+
+  @Before
+  public void setUp() throws Exception {
+    StepExecution stepExecution = new StepExecution("exportDoc", new JobExecution(1L));
+    chunkContext = new ChunkContext(new StepContext(stepExecution));
+    executionContext = stepExecution.getExecutionContext();
+    documentExporter = new DocumentExporter(reader, documentDestination, 2);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    verifyAll();
+  }
+
+  @Test
+  public void testNothingToRead() throws Exception {
+    reader.open(executionContext); expectLastCall();
+    expect(reader.read()).andReturn(null);
+    reader.close(); expectLastCall();
+    replayAll();
+
+    documentExporter.execute(null, chunkContext);
+  }
+
+  @Test
+  public void testWriteLessDocumentsThanWriteBlockSize() throws Exception {
+    reader.open(executionContext); expectLastCall();
+    expect(reader.read()).andReturn(DOCUMENT);
+    expect(documentDestination.open(DOCUMENT)).andReturn(documentItemWriter);
+    documentItemWriter.write(DOCUMENT); expectLastCall();
+    expect(reader.read()).andReturn(null);
+    reader.close(); expectLastCall();
+    documentItemWriter.close(); expectLastCall();
+    replayAll();
+
+    documentExporter.execute(null, chunkContext);
+  }
+
+  @Test
+  public void testWriteMoreDocumentsThanWriteBlockSize() throws Exception {
+    Document document2 = new Document(new HashMap<String, String>() {{ put("id", "2"); }});
+    Document document3 = new Document(new HashMap<String, String>() {{ put("id", "3"); }});
+
+    reader.open(executionContext); expectLastCall();
+    expect(reader.read()).andReturn(DOCUMENT);
+    expect(documentDestination.open(DOCUMENT)).andReturn(documentItemWriter);
+    documentItemWriter.write(DOCUMENT); expectLastCall();
+    expect(reader.read()).andReturn(document2);
+    documentItemWriter.write(document2); expectLastCall();
+    expect(reader.read()).andReturn(document3);
+    documentItemWriter.close(); expectLastCall();
+    expect(documentDestination.open(document3)).andReturn(documentItemWriter2);
+    documentItemWriter2.write(document3); expectLastCall();
+    expect(reader.read()).andReturn(null);
+    reader.update(executionContext);
+    reader.close(); expectLastCall();
+    documentItemWriter2.close(); expectLastCall();
+    replayAll();
+
+    documentExporter.execute(null, chunkContext);
+  }
+
+  @Test(expected = IOException.class)
+  public void testReadError() throws Exception {
+    reader.open(executionContext); expectLastCall();
+    expect(reader.read()).andReturn(DOCUMENT);
+    expect(documentDestination.open(DOCUMENT)).andReturn(documentItemWriter);
+    documentItemWriter.write(DOCUMENT); expectLastCall();
+    expect(reader.read()).andThrow(new IOException("TEST"));
+    documentItemWriter.revert(); expectLastCall();
+    reader.close(); expectLastCall();
+    replayAll();
+
+    documentExporter.execute(null, chunkContext);
+  }
+
+  @Test(expected = UncheckedIOException.class)
+  public void testWriteError() throws Exception {
+    reader.open(executionContext); expectLastCall();
+    expect(reader.read()).andReturn(DOCUMENT);
+    expect(documentDestination.open(DOCUMENT)).andReturn(documentItemWriter);
+    documentItemWriter.write(DOCUMENT); expectLastCall().andThrow(new UncheckedIOException(new IOException("TEST")));
+    documentItemWriter.revert(); expectLastCall();
+    reader.close(); expectLastCall();
+    replayAll();
+
+    documentExporter.execute(null, chunkContext);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentItemReaderTest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentItemReaderTest.java b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentItemReaderTest.java
new file mode 100644
index 0000000..942713f
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentItemReaderTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+package org.apache.ambari.infra.job.archive;
+
+import org.easymock.EasyMockRunner;
+import org.easymock.EasyMockSupport;
+import org.easymock.Mock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.batch.item.ExecutionContext;
+
+import java.util.HashMap;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+
+@RunWith(EasyMockRunner.class)
+public class DocumentItemReaderTest extends EasyMockSupport {
+  private static final Document DOCUMENT = new Document(new HashMap<String, String>() {{ put("id", "1"); }});
+  private static final Document DOCUMENT_2 = new Document(new HashMap<String, String>() {{ put("id", "2"); }});
+  private static final Document DOCUMENT_3 = new Document(new HashMap<String, String>() {{ put("id", "3"); }});
+  private static final int READ_BLOCK_SIZE = 2;
+
+  private DocumentItemReader documentItemReader;
+  @Mock
+  private DocumentSource documentSource;
+  @Mock
+  private DocumentIterator documentIterator;
+  @Mock
+  private DocumentIterator documentIterator2;
+
+  @Before
+  public void setUp() throws Exception {
+    documentItemReader = new DocumentItemReader(documentSource, READ_BLOCK_SIZE);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    verifyAll();
+  }
+
+  @Test
+  public void testReadWhenCollectionIsEmpty() throws Exception {
+    expect(documentSource.open(null, 2)).andReturn(documentIterator);
+    expect(documentIterator.next()).andReturn(null);
+    documentIterator.close(); expectLastCall();
+    replayAll();
+
+    assertThat(documentItemReader.read(), is(nullValue()));
+    assertThat(documentItemReader.isComplete(null), is(true));
+    assertThat(documentItemReader.isComplete(null, null), is(true));
+  }
+
+  @Test
+  public void testReadWhenCollectionContainsLessElementsThanReadBlockSize() throws Exception {
+    expect(documentSource.open(null, 2)).andReturn(documentIterator);
+    expect(documentIterator.next()).andReturn(DOCUMENT);
+    expect(documentIterator.next()).andReturn(null);
+    documentIterator.close(); expectLastCall();
+    replayAll();
+
+    assertThat(documentItemReader.read(), is(DOCUMENT));
+    assertThat(documentItemReader.isComplete(null), is(false));
+    assertThat(documentItemReader.isComplete(null, null), is(false));
+    assertThat(documentItemReader.read(), is(nullValue()));
+    assertThat(documentItemReader.isComplete(null), is(true));
+    assertThat(documentItemReader.isComplete(null, null), is(true));
+  }
+
+  @Test
+  public void testReadWhenCollectionContainsExactlySameCountElementsAsReadBlockSize() throws Exception {
+    expect(documentSource.open(null, 2)).andReturn(documentIterator);
+    expect(documentSource.open(DOCUMENT_2, 2)).andReturn(documentIterator2);
+    expect(documentIterator.next()).andReturn(DOCUMENT);
+    expect(documentIterator.next()).andReturn(DOCUMENT_2);
+    expect(documentIterator.next()).andReturn(null);
+    documentIterator.close(); expectLastCall();
+
+    expect(documentIterator2.next()).andReturn(null);
+    documentIterator2.close(); expectLastCall();
+    replayAll();
+
+    assertThat(documentItemReader.read(), is(DOCUMENT));
+    assertThat(documentItemReader.isComplete(null), is(false));
+    assertThat(documentItemReader.isComplete(null, null), is(false));
+    assertThat(documentItemReader.read(), is(DOCUMENT_2));
+    assertThat(documentItemReader.isComplete(null), is(false));
+    assertThat(documentItemReader.isComplete(null, null), is(false));
+    assertThat(documentItemReader.read(), is(nullValue()));
+    assertThat(documentItemReader.isComplete(null), is(true));
+    assertThat(documentItemReader.isComplete(null, null), is(true));
+  }
+
+  @Test
+  public void testReadWhenCollectionContainsMoreElementsThanReadBlockSize() throws Exception {
+    Document document3 = new Document(new HashMap<String, String>() {{ put("id", "2"); }});
+
+    expect(documentSource.open(null, 2)).andReturn(documentIterator);
+    expect(documentSource.open(DOCUMENT_2, 2)).andReturn(documentIterator2);
+    expect(documentIterator.next()).andReturn(DOCUMENT);
+    expect(documentIterator.next()).andReturn(DOCUMENT_2);
+    expect(documentIterator.next()).andReturn(null);
+    documentIterator.close(); expectLastCall();
+    expect(documentIterator2.next()).andReturn(document3);
+    expect(documentIterator2.next()).andReturn(null);
+    documentIterator2.close(); expectLastCall();
+
+    replayAll();
+
+    assertThat(documentItemReader.read(), is(DOCUMENT));
+    assertThat(documentItemReader.isComplete(null), is(false));
+    assertThat(documentItemReader.isComplete(null, null), is(false));
+
+    assertThat(documentItemReader.read(), is(DOCUMENT_2));
+    assertThat(documentItemReader.isComplete(null), is(false));
+    assertThat(documentItemReader.isComplete(null, null), is(false));
+
+    assertThat(documentItemReader.read(), is(document3));
+    assertThat(documentItemReader.isComplete(null), is(false));
+    assertThat(documentItemReader.isComplete(null, null), is(false));
+
+    assertThat(documentItemReader.read(), is(nullValue()));
+    assertThat(documentItemReader.isComplete(null), is(true));
+    assertThat(documentItemReader.isComplete(null, null), is(true));
+  }
+
+  @Test
+  public void testContinueWhenOnlyFirstElementWasRead() throws Exception {
+    expect(documentSource.open(null, 2)).andReturn(documentIterator);
+    expect(documentIterator.next()).andReturn(DOCUMENT);
+    documentIterator.close(); expectLastCall();
+    expect(documentSource.open(null, 2)).andReturn(documentIterator2);
+    expect(documentIterator2.next()).andReturn(DOCUMENT);
+    documentIterator2.close(); expectLastCall();
+    replayAll();
+
+    ExecutionContext executionContext = new ExecutionContext();
+    documentItemReader.open(executionContext);
+    assertThat(documentItemReader.read(), is(DOCUMENT));
+    documentItemReader.update(executionContext);
+    assertThat(executionContext.containsKey(DocumentItemReader.POSITION), is(false));
+    documentItemReader.close();
+
+    documentItemReader.open(executionContext);
+    assertThat(documentItemReader.read(), is(DOCUMENT));
+    documentItemReader.close();
+  }
+
+  @Test
+  public void testContinueWhenMoreThanOneElementWasRead() throws Exception {
+    expect(documentSource.open(null, 2)).andReturn(documentIterator);
+    expect(documentIterator.next()).andReturn(DOCUMENT);
+    expect(documentIterator.next()).andReturn(DOCUMENT_2);
+    documentIterator.close(); expectLastCall();
+    expect(documentSource.open(DOCUMENT, 2)).andReturn(documentIterator2);
+    expect(documentIterator2.next()).andReturn(DOCUMENT_2);
+    expect(documentIterator2.next()).andReturn(DOCUMENT_3);
+    documentIterator2.close(); expectLastCall();
+
+    replayAll();
+
+    ExecutionContext executionContext = new ExecutionContext();
+    documentItemReader.open(executionContext);
+    assertThat(documentItemReader.read(), is(DOCUMENT));
+    assertThat(documentItemReader.read(), is(DOCUMENT_2));
+    documentItemReader.update(executionContext);
+    assertThat(executionContext.get(DocumentItemReader.POSITION), is(DOCUMENT));
+    documentItemReader.close();
+
+    documentItemReader.open(executionContext);
+    assertThat(documentItemReader.read(), is(DOCUMENT_2));
+    assertThat(documentItemReader.read(), is(DOCUMENT_3));
+    documentItemReader.close();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriterTest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriterTest.java b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriterTest.java
new file mode 100644
index 0000000..6411ff1
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/LocalDocumentItemWriterTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package org.apache.ambari.infra.job.archive;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.FileUtils;
+import org.easymock.EasyMockRunner;
+import org.easymock.EasyMockSupport;
+import org.easymock.Mock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(EasyMockRunner.class)
+public class LocalDocumentItemWriterTest extends EasyMockSupport {
+
+  private static final Document DOCUMENT = new Document(new HashMap<String, String>() {{ put("id", "1"); }});
+  private static final Document DOCUMENT2 = new Document(new HashMap<String, String>() {{ put("id", "2"); }});
+  private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+  private LocalDocumentItemWriter localDocumentItemWriter;
+  private File outFile;
+  @Mock
+  private FileAction fileAction;
+
+  @Before
+  public void setUp() throws Exception {
+    outFile = File.createTempFile("LocalDocumentItemWriterTest", "json.tmp");
+    localDocumentItemWriter = new LocalDocumentItemWriter(outFile, fileAction);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    outFile.delete();
+    verifyAll();
+  }
+
+  @Test
+  public void testWrite() throws Exception {
+    expect(fileAction.perform(outFile)).andReturn(outFile);
+    replayAll();
+
+    localDocumentItemWriter.write(DOCUMENT);
+    localDocumentItemWriter.write(DOCUMENT2);
+    localDocumentItemWriter.close();
+
+    List<Document> documentList = readBack(outFile);
+    assertThat(documentList.size(), is(2));
+    assertThat(documentList.get(0).get("id"), is(DOCUMENT.get("id")));
+    assertThat(documentList.get(1).get("id"), is(DOCUMENT2.get("id")));
+  }
+
+  private List<Document> readBack(File file) throws IOException {
+    List<Document> documentList = new ArrayList<>();
+    for (String line : FileUtils.readLines(file)) {
+      documentList.add(OBJECT_MAPPER.readValue(line, Document.class));
+    }
+    return documentList;
+  }
+
+  @Test
+  public void testRevert() throws Exception {
+    replayAll();
+
+    localDocumentItemWriter.write(DOCUMENT);
+    localDocumentItemWriter.revert();
+
+    assertThat(outFile.exists(), is(false));
+  }
+}
\ No newline at end of file


[11/50] [abbrv] ambari git commit: AMBARI-22517. NPE during Ambari schema upgrade while updating Hive configs.

Posted by ao...@apache.org.
AMBARI-22517. NPE during Ambari schema upgrade while updating Hive configs.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c9936ad3
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c9936ad3
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c9936ad3

Branch: refs/heads/branch-3.0-perf
Commit: c9936ad349e3e703dcbf6f2a1644f8a3e45a23d0
Parents: c5fe6cb
Author: Swapan Shridhar <ss...@hortonworks.com>
Authored: Mon Nov 27 00:47:57 2017 -0800
Committer: Swapan Shridhar <ss...@hortonworks.com>
Committed: Mon Nov 27 00:47:57 2017 -0800

----------------------------------------------------------------------
 .../server/upgrade/UpgradeCatalog260.java       | 38 ++++++++++----------
 1 file changed, 20 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c9936ad3/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
index 33b62f8..4d9a5da 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog260.java
@@ -775,26 +775,28 @@ public class UpgradeCatalog260 extends AbstractUpgradeCatalog {
           // hive-interactive-site/hive.llap.zk.sm.keytab.file and hive-interactive-site/hive.llap.task.keytab.file respectively,
           // based on what hive-interactive-site/hive.llap.daemon.keytab.file has.
           Config hsiSiteConfig = cluster.getDesiredConfigByType(HIVE_INTERACTIVE_SITE);
-          Map<String, String> hsiSiteConfigProperties = hsiSiteConfig.getProperties();
-          if (hsiSiteConfigProperties != null &&
-                  hsiSiteConfigProperties.containsKey(HIVE_LLAP_DAEMON_KEYTAB_FILE)) {
-            String[] identities = {HIVE_LLAP_ZK_SM_KEYTAB_FILE, HIVE_LLAP_TASK_KEYTAB_FILE};
-            Map<String, String> newProperties = new HashMap<>();
-            for (String identity : identities) {
-              // Update only if we were able to modify the corresponding kerberos descriptor,
-              // reflected in list 'getYarnKerberosDescUpdatedList'.
-              if (getYarnKerberosDescUpdatedList().contains(identity) && hsiSiteConfigProperties.containsKey(identity)) {
-                newProperties.put(identity, hsiSiteConfigProperties.get(HIVE_LLAP_DAEMON_KEYTAB_FILE));
+          if (hsiSiteConfig != null) {
+            Map<String, String> hsiSiteConfigProperties = hsiSiteConfig.getProperties();
+            if (hsiSiteConfigProperties != null &&
+                    hsiSiteConfigProperties.containsKey(HIVE_LLAP_DAEMON_KEYTAB_FILE)) {
+              String[] identities = {HIVE_LLAP_ZK_SM_KEYTAB_FILE, HIVE_LLAP_TASK_KEYTAB_FILE};
+              Map<String, String> newProperties = new HashMap<>();
+              for (String identity : identities) {
+                // Update only if we were able to modify the corresponding kerberos descriptor,
+                // reflected in list 'getYarnKerberosDescUpdatedList'.
+                if (getYarnKerberosDescUpdatedList().contains(identity) && hsiSiteConfigProperties.containsKey(identity)) {
+                  newProperties.put(identity, hsiSiteConfigProperties.get(HIVE_LLAP_DAEMON_KEYTAB_FILE));
+                }
               }
-            }
 
-            // Update step.
-            if (newProperties.size() > 0) {
-              try {
-                updateConfigurationPropertiesForCluster(cluster, HIVE_INTERACTIVE_SITE, newProperties, true, false);
-                LOG.info("Updated HSI config(s) : " + newProperties.keySet() + " with value(s) = " + newProperties.values()+" respectively.");
-              } catch (AmbariException e) {
-                e.printStackTrace();
+              // Update step.
+              if (newProperties.size() > 0) {
+                try {
+                  updateConfigurationPropertiesForCluster(cluster, HIVE_INTERACTIVE_SITE, newProperties, true, false);
+                  LOG.info("Updated HSI config(s) : " + newProperties.keySet() + " with value(s) = " + newProperties.values() + " respectively.");
+                } catch (AmbariException e) {
+                  e.printStackTrace();
+                }
               }
             }
           }


[42/50] [abbrv] ambari git commit: AMBARI-22554. UI should pass repo_name for repository validation (vsubramanian)

Posted by ao...@apache.org.
AMBARI-22554. UI should pass repo_name for repository validation (vsubramanian)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ca174fb3
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ca174fb3
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ca174fb3

Branch: refs/heads/branch-3.0-perf
Commit: ca174fb32a0e34582776b0607b6a2d14dc72c20d
Parents: 323ce7a
Author: Vivek Ratnavel Subramanian <vi...@gmail.com>
Authored: Wed Nov 29 16:22:20 2017 -0800
Committer: Vivek Ratnavel Subramanian <vi...@gmail.com>
Committed: Wed Nov 29 16:22:20 2017 -0800

----------------------------------------------------------------------
 .../main/resources/ui/admin-web/app/scripts/services/Stack.js   | 3 ++-
 ambari-web/app/controllers/installer.js                         | 5 ++++-
 2 files changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ca174fb3/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js
index 90f4f48..f52e687 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Stack.js
@@ -405,7 +405,8 @@ angular.module('ambariAdminConsole')
               $http.post(url + '/operating_systems/' + os.OperatingSystems.os_type + '/repositories/' + repo.Repositories.repo_id + '?validate_only=true',
                 {
                   "Repositories": {
-                    "base_url": repo.Repositories.base_url
+                    "base_url": repo.Repositories.base_url,
+                    "repo_name": repo.Repositories.repo_name
                   }
                 },
                 {

http://git-wip-us.apache.org/repos/asf/ambari/blob/ca174fb3/ambari-web/app/controllers/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js
index d6be78d..f49fc11 100644
--- a/ambari-web/app/controllers/installer.js
+++ b/ambari-web/app/controllers/installer.js
@@ -315,7 +315,9 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
       App.Repository.find().findProperty('id', repo.id).set('baseUrl', repo.base_url);
     });
     _oses.forEach(function (os) {
-      App.OperatingSystem.find().findProperty('id', os.id).set('isSelected', os.is_selected);
+      if (App.OperatingSystem.find().findProperty('id', os.id)) {
+        App.OperatingSystem.find().findProperty('id', os.id).set('isSelected', os.is_selected);
+      }
     });
     //should delete the record on going to step 2, on going back to step 1, still need the record
     if (App.router.get('currentState.name') != "step1") {
@@ -863,6 +865,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, {
                   data: {
                     'Repositories': {
                       'base_url': repo.get('baseUrl'),
+                      'repo_name': repo.get('repoName'),
                       "verify_base_url": verifyBaseUrl
                     }
                   }


[38/50] [abbrv] ambari git commit: AMBARI-22480. Validate blueprint does not allow lzo enable without setup with license agreement. JavaDocs update. (mpapirkovskyy)

Posted by ao...@apache.org.
AMBARI-22480. Validate blueprint does not allow lzo enable without setup with license agreement. JavaDocs update. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/82692bd2
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/82692bd2
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/82692bd2

Branch: refs/heads/branch-3.0-perf
Commit: 82692bd29d6cbc4f1eba0ae4e442e1d691843cb2
Parents: 9bbc0ef
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Tue Nov 21 17:16:51 2017 +0200
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Wed Nov 29 18:30:08 2017 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/ambari/server/topology/BlueprintImpl.java  | 1 +
 .../java/org/apache/ambari/server/topology/BlueprintValidator.java  | 1 +
 2 files changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/82692bd2/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
index 6801e33..be3547a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
@@ -351,6 +351,7 @@ public class BlueprintImpl implements Blueprint {
    * Validate blueprint configuration.
    *
    * @throws InvalidTopologyException if the blueprint configuration is invalid
+   * @throws GPLLicenseNotAcceptedException ambari was configured to use gpl software, but gpl license is not accepted
    */
   @Override
   public void validateRequiredProperties() throws InvalidTopologyException, GPLLicenseNotAcceptedException {

http://git-wip-us.apache.org/repos/asf/ambari/blob/82692bd2/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
index 156fe8c..0f83168 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
@@ -36,6 +36,7 @@ public interface BlueprintValidator {
    * This doesn't include password properties.
    *
    * @throws InvalidTopologyException if required properties are not set in blueprint
+   * @throws GPLLicenseNotAcceptedException ambari was configured to use gpl software, but gpl license is not accepted
    */
   void validateRequiredProperties() throws InvalidTopologyException, GPLLicenseNotAcceptedException;
 }


[14/50] [abbrv] ambari git commit: AMBARI-22519 Admin View: add ability to change roles. (atkach)

Posted by ao...@apache.org.
AMBARI-22519 Admin View: add ability to change roles. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/32e25b80
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/32e25b80
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/32e25b80

Branch: refs/heads/branch-3.0-perf
Commit: 32e25b80c43158bd7114f11825eaa590c9b7e8b0
Parents: 3dca560
Author: Andrii Tkach <at...@apache.org>
Authored: Mon Nov 27 14:18:59 2017 +0200
Committer: Andrii Tkach <at...@apache.org>
Committed: Mon Nov 27 15:41:01 2017 +0200

----------------------------------------------------------------------
 .../main/resources/ui/admin-web/app/index.html  |   1 -
 .../userManagement/GroupCreateCtrl.js           |  32 +-
 .../controllers/userManagement/GroupEditCtrl.js | 162 +++++++---
 .../userManagement/GroupsListCtrl.js            |  17 +-
 .../userManagement/UserCreateCtrl.js            |  25 +-
 .../controllers/userManagement/UserEditCtrl.js  | 304 ++++++++++++-------
 .../userManagement/UserManagementCtrl.js        |   4 +-
 .../controllers/userManagement/UsersListCtrl.js |  69 +++--
 .../ui/admin-web/app/scripts/i18n.config.js     |   6 +-
 .../admin-web/app/scripts/services/Cluster.js   |  90 +++---
 .../ui/admin-web/app/scripts/services/Group.js  | 144 ++++-----
 .../app/scripts/services/GroupConstants.js      |  38 ---
 .../app/scripts/services/RoleDetailsModal.js    |   5 +-
 .../ui/admin-web/app/scripts/services/User.js   |  17 +-
 .../resources/ui/admin-web/app/styles/main.css  |   5 -
 .../ui/admin-web/app/styles/user-management.css |  13 +
 .../app/views/remoteClusters/list.html          |   5 +-
 .../admin-web/app/views/stackVersions/list.html |   7 +-
 .../app/views/userManagement/groupEdit.html     | 149 +++++----
 .../app/views/userManagement/main.html          |   4 +-
 .../userManagement/modals/groupCreate.html      |   8 +-
 .../views/userManagement/modals/userCreate.html |  10 +-
 .../app/views/userManagement/userEdit.html      |  48 ++-
 .../app/views/userManagement/usersList.html     |   2 +-
 24 files changed, 647 insertions(+), 518 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/index.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/index.html b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
index e3b817e..bf033e6 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/index.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
@@ -153,7 +153,6 @@
 <script src="scripts/services/Utility.js"></script>
 <script src="scripts/services/UserConstants.js"></script>
 <script src="scripts/services/User.js"></script>
-<script src="scripts/services/GroupConstants.js"></script>
 <script src="scripts/services/Group.js"></script>
 <script src="scripts/services/RemoteCluster.js"></script>
 <script src="scripts/services/View.js"></script>

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
index 94a2c9f..a34033b 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
@@ -19,8 +19,8 @@
 
 angular.module('ambariAdminConsole')
 .controller('GroupCreateCtrl',
-['$scope', '$rootScope', 'Group', '$location', 'Alert', 'UnsavedDialog', '$translate', '$modalInstance', 'Cluster',
-function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate, $modalInstance, Cluster) {
+['$scope', '$rootScope', 'Group', '$location', 'Alert', 'UnsavedDialog', '$translate', '$modalInstance', 'Cluster', 'RoleDetailsModal',
+function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate, $modalInstance, Cluster, RoleDetailsModal) {
   var $t = $translate.instant;
 
   $scope.form = {};
@@ -33,10 +33,8 @@ function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate,
 
 
   function loadRoles() {
-    Cluster.getPermissions().then(function(data) {
-      $scope.roleOptions = data.map(function(item) {
-        return item.PermissionInfo;
-      });
+    return Cluster.getRoleOptions().then(function (data) {
+      $scope.roleOptions = data;
     });
   }
 
@@ -60,6 +58,9 @@ function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate,
   }
 
   function saveMembers(group, members) {
+    if (!members.length) {
+      return;
+    }
     group.members = members.filter(function(item) {
       return item.trim();
     }).map(function(item) {
@@ -70,6 +71,12 @@ function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate,
     });
   }
 
+  $scope.showHelpPage = function() {
+    Cluster.getRolesWithAuthorizations().then(function(roles) {
+      RoleDetailsModal.show(roles);
+    });
+  };
+
   $scope.save = function () {
     $scope.form.groupCreateForm.submitted = true;
     if ($scope.form.groupCreateForm.$valid) {
@@ -87,21 +94,22 @@ function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate,
   };
 
   function saveRole() {
+    if (!$scope.formData.role || $scope.formData.role === 'NONE') {
+      return;
+    }
     Cluster.createPrivileges(
       {
         clusterId: $rootScope.cluster.Clusters.cluster_name
       },
       [{PrivilegeInfo: {
-        permission_name: $scope.roleOptions.filter(function(role) {
-          return role.permission_id == Number($scope.formData.role);
-        })[0].permission_name,
+        permission_name: $scope.formData.role,
         principal_name: $scope.formData.groupName,
         principal_type: 'GROUP'
       }}]
     )
-      .catch(function(data) {
-        Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
-      });
+    .catch(function(data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
   }
 
   $scope.cancel = function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
index ff705eb..8855317 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
@@ -19,9 +19,14 @@
 
 angular.module('ambariAdminConsole')
 .controller('GroupEditCtrl',
-['$scope', 'Group', '$routeParams', 'Cluster', 'View', 'Alert', 'ConfirmationModal', '$location', 'GroupConstants', '$translate',
-function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $location, GroupConstants, $translate) {
+['$scope', '$rootScope', 'Group', '$routeParams', 'Cluster', 'View', 'Alert', 'ConfirmationModal', '$location', '$translate', 'RoleDetailsModal',
+function($scope, $rootScope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $location,  $translate, RoleDetailsModal) {
   var $t = $translate.instant;
+  var nonRole = {
+    permission_name: 'NONE',
+    permission_label: $t('users.roles.none')
+  };
+
   $scope.constants = {
     group: $t('common.group'),
     view: $t('common.view').toLowerCase(),
@@ -32,7 +37,6 @@ function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $
   $scope.group.editingUsers = [];
   $scope.groupMembers = [];
   $scope.dataLoaded = false;
-  
   $scope.isMembersEditing = false;
 
   $scope.$watch(function() {
@@ -62,30 +66,11 @@ function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $
     $scope.group.saveMembers().catch(function(data) {
         Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
       }).finally(function() {
-        loadMembers();
+        loadGroup();
       });
     $scope.isMembersEditing = false;
   };
 
-
-  function loadMembers(){
-    $scope.group.getMembers().then(function(members) {
-      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
-      $scope.groupMembers = members;
-      $scope.group.editingUsers = angular.copy($scope.groupMembers);
-    });
-  }    
-  
-  $scope.group.isLDAP().then(function(isLDAP) {
-    $scope.group.ldap_group = isLDAP;
-    $scope.group.getGroupType().then(function() {
-      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
-    });
-    loadMembers();
-  });
-
-  $scope.group.getGroupType();
-
   $scope.deleteGroup = function(group) {
     ConfirmationModal.show(
       $t('common.delete', {
@@ -119,12 +104,9 @@ function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $
           });
         }
         group.destroy().then(function() {
-          $location.path('/userManagement');
+          $location.path('/userManagement?tab=groups');
           if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
+            Cluster.deleteMultiplePrivileges($rootScope.cluster.Clusters.cluster_name, clusterPrivilegesIds);
           }
           angular.forEach(viewsPrivileges, function(privilege) {
             View.deletePrivilege(privilege);
@@ -135,7 +117,7 @@ function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $
   };
 
 
-  $scope.removePrivilege = function(name, privilege) {
+  $scope.removeViewPrivilege = function(name, privilege) {
     var privilegeObject = {
         id: privilege.privilege_id,
         view_name: privilege.view_name,
@@ -143,40 +125,124 @@ function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $
         instance_name: name
     };
     View.deletePrivilege(privilegeObject).then(function() {
-      loadPrivileges();
+      loadGroup();
     });
   };
 
-function loadPrivileges() {
-  // Load privileges
-  Group.getPrivileges($routeParams.id).then(function(data) {
+  $scope.showHelpPage = function() {
+    Cluster.getRolesWithAuthorizations().then(function(roles) {
+      RoleDetailsModal.show(roles);
+    });
+  };
+
+  $scope.updateRole = function () {
+    var clusterName = $rootScope.cluster.Clusters.cluster_name;
+    if ($scope.originalRole.permission_name !== $scope.currentRole.permission_name) {
+      if ($scope.currentRole.permission_name === 'NONE') {
+        deleteGroupRoles(clusterName, $scope.group).finally(loadGroup);
+      } else {
+        if ($scope.group.roles.length) {
+          deleteGroupRoles(clusterName, $scope.group, true).finally(function() {
+            addGroupRoles(clusterName, $scope.currentRole, $scope.group).finally(loadGroup);
+          });
+        } else {
+          addGroupRoles(clusterName, $scope.currentRole, $scope.group).finally(loadGroup);
+        }
+      }
+    }
+  };
+
+  function deleteGroupRoles(clusterName, group, ignoreAlert) {
+    return Cluster.deleteMultiplePrivileges(
+      clusterName,
+      group.roles.map(function(item) {
+        return item.privilege_id;
+      })
+    ).then(function () {
+      if (!ignoreAlert) {
+        Alert.success($t('users.alerts.roleChangedToNone', {
+          user_name: group.group_name
+        }));
+      }
+    }).catch(function (data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
+  }
+
+  function addGroupRoles(clusterName, newRole, group) {
+    return Cluster.createPrivileges(
+      {
+        clusterId: clusterName
+      },
+      [{
+        PrivilegeInfo: {
+          permission_name: newRole.permission_name,
+          principal_name: group.group_name,
+          principal_type: 'GROUP'
+        }
+      }]
+    ).then(function () {
+      Alert.success($t('users.alerts.roleChanged', {
+        name: group.group_name,
+        role: newRole.permission_label
+      }));
+    }).catch(function (data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
+  }
+
+  function parsePrivileges(rawPrivileges) {
     var privileges = {
       clusters: {},
       views: {}
     };
-    angular.forEach(data.data.items, function(privilege) {
+    angular.forEach(rawPrivileges, function (privilege) {
       privilege = privilege.PrivilegeInfo;
-      if(privilege.type === 'CLUSTER'){
+      if (privilege.type === 'CLUSTER') {
         // This is cluster
         privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || [];
         privileges.clusters[privilege.cluster_name].push(privilege.permission_label);
-      } else if ( privilege.type === 'VIEW'){
-        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
-        privileges.views[privilege.instance_name].version = privilege.version;
-        privileges.views[privilege.instance_name].view_name = privilege.view_name;
-        privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
-        privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+      } else if (privilege.type === 'VIEW') {
+        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || {
+          privileges: [],
+          version: privilege.version,
+          view_name: privilege.view_name,
+          privilege_id: privilege.privilege_id
+        };
+        if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) === -1) {
+          privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+        }
       }
     });
 
-    $scope.privileges = data.data.items.length ? privileges : null;
+    $scope.privileges = privileges;
     $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
     $scope.noViewPriv = $.isEmptyObject(privileges.views);
     $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
-    $scope.dataLoaded = true;
-  }).catch(function(data) {
-    Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
-  });
-}
-loadPrivileges();
+  }
+
+  function loadGroup() {
+    Group.get($routeParams.id).then(function(group) {
+      $scope.group = group;
+      parsePrivileges(group.privileges);
+      var clusterRole = $scope.group.roles[0];
+      $scope.currentRole = clusterRole || nonRole;
+      $scope.originalRole = clusterRole || nonRole;
+      $scope.groupMembers = group.members.map(function(item) {
+        return item.MemberInfo.user_name;
+      });
+      $scope.group.editingUsers = angular.copy($scope.groupMembers);
+    }).finally(function() {
+      $scope.dataLoaded = true;
+    });
+  }
+
+  function loadRoles() {
+    return Cluster.getRoleOptions().then(function(data) {
+      $scope.roleOptions = data;
+    });
+  }
+
+  loadRoles().finally(loadGroup);
+
 }]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
index af77ba9..61b5282 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
@@ -19,8 +19,8 @@
 
 angular.module('ambariAdminConsole')
 .controller('GroupsListCtrl',
-['$scope', 'Group', '$modal', 'ConfirmationModal', '$rootScope', 'GroupConstants', '$translate', 'Settings', 'Cluster', 'View', '$location',
-function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $translate, Settings, Cluster, View, $location) {
+['$scope', 'Group', '$modal', 'ConfirmationModal', '$rootScope', '$translate', 'Settings', 'Cluster', 'View', 'Alert',
+function($scope, Group, $modal, ConfirmationModal, $rootScope, $translate, Settings, Cluster, View, Alert) {
   var $t = $translate.instant;
   $scope.constants = {
     groups: $t('common.groups').toLowerCase()
@@ -70,15 +70,15 @@ function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $
       $scope.tableInfo.showed = groups.length;
     })
     .catch(function(data) {
-      console.error($t('groups.alerts.getGroupsListError'));
+      Alert.error($t('groups.alerts.getGroupsListError'), data.data.message);
     });
   }
 
   $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
-    .concat(Object.keys(GroupConstants.TYPES).map(function(key) {
+    .concat(Object.keys(Group.getTypes()).map(function(key) {
       return {
-        label: $t(GroupConstants.TYPES[key].LABEL_KEY),
-        value: GroupConstants.TYPES[key].VALUE
+        label: $t(Group.getTypes()[key].LABEL_KEY),
+        value: Group.getTypes()[key].VALUE
       };
   }));
   $scope.filter.type = $scope.typeFilterOptions[0];
@@ -153,10 +153,7 @@ function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $
         }
         group.destroy().then(function() {
           if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
+            Cluster.deleteMultiplePrivileges($rootScope.cluster.Clusters.cluster_name, clusterPrivilegesIds);
           }
           angular.forEach(viewsPrivileges, function(privilege) {
             View.deletePrivilege(privilege);

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
index 34637ae..3b29b90 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
@@ -19,8 +19,8 @@
 
 angular.module('ambariAdminConsole')
 .controller('UserCreateCtrl',
-['$scope', '$rootScope', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', 'Cluster', '$modalInstance',
-function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate, Cluster, $modalInstance) {
+['$scope', '$rootScope', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', 'Cluster', '$modalInstance', 'RoleDetailsModal',
+function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate, Cluster, $modalInstance, RoleDetailsModal) {
   var $t = $translate.instant;
 
   $scope.form = {};
@@ -28,17 +28,15 @@ function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate,
     userName: '',
     password: '',
     confirmPassword: '',
-    role: null,
+    role: '',
     isAdmin: false,
     isActive: true
   };
   $scope.roleOptions = [];
 
   function loadRoles() {
-    Cluster.getPermissions().then(function(data) {
-      $scope.roleOptions = data.map(function(item) {
-        return item.PermissionInfo;
-      });
+    return Cluster.getRoleOptions().then(function (data) {
+      $scope.roleOptions = data;
     });
   }
 
@@ -61,6 +59,12 @@ function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate,
     }
   }
 
+  $scope.showHelpPage = function() {
+    Cluster.getRolesWithAuthorizations().then(function(roles) {
+      RoleDetailsModal.show(roles);
+    });
+  };
+
   $scope.save = function () {
     $scope.form.userCreateForm.submitted = true;
     if ($scope.form.userCreateForm.$valid) {
@@ -83,14 +87,15 @@ function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate,
   };
 
   function saveRole() {
+    if (!$scope.formData.role || $scope.formData.role === 'NONE') {
+      return;
+    }
     Cluster.createPrivileges(
       {
         clusterId: $rootScope.cluster.Clusters.cluster_name
       },
       [{PrivilegeInfo: {
-        permission_name: $scope.roleOptions.filter(function(role) {
-          return role.permission_id == Number($scope.formData.role);
-        })[0].permission_name,
+        permission_name: $scope.formData.role,
         principal_name: $scope.formData.userName,
         principal_type: 'USER'
       }}]

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
index 001bb1b..a3c96cd 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
@@ -18,9 +18,15 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('UserEditCtrl', ['$scope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', function($scope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate) {
+.controller('UserEditCtrl',
+['$scope', '$rootScope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', 'RoleDetailsModal',
+function($scope, $rootScope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate, RoleDetailsModal) {
 
   var $t = $translate.instant;
+  var nonRole = {
+    permission_name: 'NONE',
+    permission_label: $t('users.roles.none')
+  };
 
   $scope.constants = {
     user: $t('common.user'),
@@ -31,77 +37,95 @@ angular.module('ambariAdminConsole')
     cluster: $t('common.cluster').toLowerCase()
   };
 
-  function loadUserInfo(){
-    User.get($routeParams.id).then(function(data) {
-      $scope.user = User.makeUser(data).Users;
-      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
-      $scope.editingGroupsList = angular.copy($scope.user.groups);
-    });
-  }
-
-  loadUserInfo();
-  $scope.user;
+  $scope.user = null;
   $scope.isCurrentUser = true;
   $scope.dataLoaded = false;
-
   $scope.isGroupEditing = false;
-  $scope.enableGroupEditing = function() {
+
+  $scope.enableGroupEditing = function () {
     $scope.isGroupEditing = true;
     $scope.editingGroupsList = angular.copy($scope.user.groups);
   };
 
-  $scope.$watch(function() {
+  $scope.$watch(function () {
     return $scope.editingGroupsList;
-  }, function(newValue) {
-    if(newValue){
-      if( !angular.equals(newValue, $scope.user.groups) ){
+  }, function (newValue) {
+    if (newValue) {
+      if (!angular.equals(newValue, $scope.user.groups)) {
         $scope.updateGroups();
       }
     }
   }, true);
 
-  $scope.updateGroups = function() {
-    var groups = $scope.editingGroupsList.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
+  $scope.showHelpPage = function() {
+    Cluster.getRolesWithAuthorizations().then(function(roles) {
+      RoleDetailsModal.show(roles);
+    });
+  };
+
+  $scope.updateRole = function () {
+    var clusterName = $rootScope.cluster.Clusters.cluster_name;
+    if ($scope.originalRole.permission_name !== $scope.currentRole.permission_name) {
+      if ($scope.currentRole.permission_name === 'NONE') {
+        deleteUserRoles(clusterName, $scope.user).finally(loadUserInfo);
+      } else {
+        if ($scope.user.roles.length) {
+          deleteUserRoles(clusterName, $scope.user, true).finally(function() {
+            addUserRoles(clusterName, $scope.currentRole, $scope.user).finally(loadUserInfo);
+          });
+        } else {
+          addUserRoles(clusterName, $scope.currentRole, $scope.user).finally(loadUserInfo);
+        }
+      }
+    }
+  };
+
+  $scope.updateGroups = function () {
+    var groups = $scope.editingGroupsList.filter(function (item) {
+      return item.trim();
+    }).map(function (item) {
+      return item.trim();
+    });
     var diff = getDifference($scope.user.groups, groups);
     var promises = [];
     // Remove user from groups
-    angular.forEach(diff.del, function(groupName) {
-      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function(data) {
+    angular.forEach(diff.del, function (groupName) {
+      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function (data) {
         Alert.error($t('users.alerts.removeUserError'), data.data.message);
       }));
     });
     // Add user to groups
-    angular.forEach(diff.add, function(groupName) {
-      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function(data) {
+    angular.forEach(diff.add, function (groupName) {
+      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function (data) {
         Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
       }));
     });
-    $q.all(promises).then(function() {
+    $q.all(promises).then(function () {
       loadUserInfo();
     });
     $scope.isGroupEditing = false;
   };
 
-  $scope.getUserMembership = function(userType) {
-    if(userType) {
-	return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
+  $scope.getUserMembership = function (userType) {
+    if (userType) {
+      return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
     }
   };
 
-  $scope.cancelUpdate = function() {
+  $scope.cancelUpdate = function () {
     $scope.isGroupEditing = false;
     $scope.editingGroupsList = '';
   };
 
-  $scope.openChangePwdDialog = function() {
+  $scope.openChangePwdDialog = function () {
     var modalInstance = $modal.open({
       templateUrl: 'views/userManagement/modals/changePassword.html',
       resolve: {
-        userName: function() {
+        userName: function () {
           return $scope.user.user_name;
         }
       },
-      controller: ['$scope', 'userName', function($scope, userName) {
+      controller: ['$scope', 'userName', function ($scope, userName) {
         $scope.passwordData = {
           password: '',
           currentUserPassword: ''
@@ -110,55 +134,54 @@ angular.module('ambariAdminConsole')
         $scope.form = {};
         $scope.userName = userName;
 
-        $scope.ok = function() {
+        $scope.ok = function () {
           $scope.form.passwordChangeForm.submitted = true;
-          if($scope.form.passwordChangeForm.$valid){
-
+          if ($scope.form.passwordChangeForm.$valid) {
             modalInstance.close({
-              password: $scope.passwordData.password, 
+              password: $scope.passwordData.password,
               currentUserPassword: $scope.passwordData.currentUserPassword
             });
           }
         };
-        $scope.cancel = function() {
+        $scope.cancel = function () {
           modalInstance.dismiss('cancel');
         };
       }]
     });
 
-    modalInstance.result.then(function(data) {
-      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function() {
+    modalInstance.result.then(function (data) {
+      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function () {
         Alert.success($t('users.alerts.passwordChanged'));
-      }).catch(function(data) {
+      }).catch(function (data) {
         Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
       });
-    }); 
+    });
   };
 
-  $scope.toggleUserActive = function() {
-    if(!$scope.isCurrentUser){
-      var newStatusKey = $scope.user.active ? 'inactive' : 'active',
-        newStatus = $t('users.' + newStatusKey).toLowerCase();
+  $scope.toggleUserActive = function () {
+    if (!$scope.isCurrentUser) {
+      var newStatusKey = $scope.user.active ? 'inactive' : 'active';
       ConfirmationModal.show(
         $t('users.changeStatusConfirmation.title'),
         $t('users.changeStatusConfirmation.message', {
           userName: $scope.user.user_name,
-          status: newStatus
+          status: $t('users.' + newStatusKey).toLowerCase()
         })
-      ).then(function() {
+      ).then(function () {
         User.setActive($scope.user.user_name, $scope.user.active)
-          .catch(function(data) {
-            Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
-            $scope.user.active = !$scope.user.active;
-          });
+        .catch(function (data) {
+          Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
+          $scope.user.active = !$scope.user.active;
+        });
       })
-      .catch(function() {
+      .catch(function () {
         $scope.user.active = !$scope.user.active;
       });
     }
-  };    
-  $scope.toggleUserAdmin = function() {
-    if(!$scope.isCurrentUser){
+  };
+
+  $scope.toggleUserAdmin = function () {
+    if (!$scope.isCurrentUser) {
       var action = $scope.user.admin ?
         $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
       ConfirmationModal.show(
@@ -167,36 +190,35 @@ angular.module('ambariAdminConsole')
           action: action,
           userName: $scope.user.user_name
         })
-      ).then(function() {
+      ).then(function () {
         User.setAdmin($scope.user.user_name, $scope.user.admin)
-        .then(function() {
-          loadPrivileges();
+        .then(function () {
+          loadUserInfo();
         })
         .catch(function (data) {
           Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
           $scope.user.admin = !$scope.user.admin;
         });
       })
-      .catch(function() {
+      .catch(function () {
         $scope.user.admin = !$scope.user.admin;
       });
-
     }
   };
 
-  $scope.removePrivilege = function(name, privilege) {
+  $scope.removeViewPrivilege = function (name, privilege) {
     var privilegeObject = {
-        id: privilege.privilege_id,
-        view_name: privilege.view_name,
-        version: privilege.version,
-        instance_name: name
+      id: privilege.privilege_id,
+      view_name: privilege.view_name,
+      version: privilege.version,
+      instance_name: name
     };
-    View.deletePrivilege(privilegeObject).then(function() {
-      loadPrivileges();
+    View.deletePrivilege(privilegeObject).then(function () {
+      loadUserInfo();
     });
   };
 
-  $scope.deleteUser = function() {
+  $scope.deleteUser = function () {
     ConfirmationModal.show(
       $t('common.delete', {
         term: $t('common.user')
@@ -205,15 +227,15 @@ angular.module('ambariAdminConsole')
         instanceType: $t('common.user').toLowerCase(),
         instanceName: '"' + $scope.user.user_name + '"'
       })
-    ).then(function() {
+    ).then(function () {
       Cluster.getPrivilegesForResource({
-        nameFilter : $scope.user.user_name,
-        typeFilter : {value: 'USER'}
-      }).then(function(data) {
+        nameFilter: $scope.user.user_name,
+        typeFilter: {value: 'USER'}
+      }).then(function (data) {
         var clusterPrivilegesIds = [];
         var viewsPrivileges = [];
         if (data.items && data.items.length) {
-          angular.forEach(data.items[0].privileges, function(privilege) {
+          angular.forEach(data.items[0].privileges, function (privilege) {
             if (privilege.PrivilegeInfo.principal_type === 'USER') {
               if (privilege.PrivilegeInfo.type === 'VIEW') {
                 viewsPrivileges.push({
@@ -228,15 +250,12 @@ angular.module('ambariAdminConsole')
             }
           });
         }
-        User.delete($scope.user.user_name).then(function() {
-          $location.path('/userManagement');
+        User.delete($scope.user.user_name).then(function () {
+          $location.path('/userManagement?tab=users');
           if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
+            Cluster.deleteMultiplePrivileges($rootScope.cluster.Clusters.cluster_name, clusterPrivilegesIds);
           }
-          angular.forEach(viewsPrivileges, function(privilege) {
+          angular.forEach(viewsPrivileges, function (privilege) {
             View.deletePrivilege(privilege);
           });
         });
@@ -244,47 +263,102 @@ angular.module('ambariAdminConsole')
     });
   };
 
-  // Load privileges
-  function loadPrivileges(){
-    User.getPrivileges($routeParams.id).then(function(data) {
-      var privileges = {
-        clusters: {},
-        views: {}
-      };
-      angular.forEach(data.data.items, function(privilege) {
-        privilege = privilege.PrivilegeInfo;
-        if(privilege.type === 'CLUSTER'){
-          // This is cluster
-          if (privileges.clusters[privilege.cluster_name]) {
-            var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
-            var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
-            // replace when cur is a more powerful role
-            if (curIndex < preIndex) {
-              privileges.clusters[privilege.cluster_name] = privilege;
-            }
-          } else {
+  function deleteUserRoles(clusterName, user, ignoreAlert) {
+    return Cluster.deleteMultiplePrivileges(
+      clusterName,
+      user.roles.map(function(item) {
+        return item.privilege_id;
+      })
+    ).then(function () {
+      if (!ignoreAlert) {
+        Alert.success($t('users.alerts.roleChangedToNone', {
+          user_name: user.user_name
+        }));
+      }
+    }).catch(function (data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
+  }
+
+  function addUserRoles(clusterName, newRole, user) {
+    return Cluster.createPrivileges(
+      {
+        clusterId: clusterName
+      },
+      [{
+        PrivilegeInfo: {
+          permission_name: newRole.permission_name,
+          principal_name: user.user_name,
+          principal_type: 'USER'
+        }
+      }]
+    ).then(function () {
+      Alert.success($t('users.alerts.roleChanged', {
+        name: user.user_name,
+        role: newRole.permission_label
+      }));
+    }).catch(function (data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
+  }
+
+  function loadUserInfo() {
+    return User.getWithRoles($routeParams.id).then(function (data) {
+      $scope.user = User.makeUser(data.data).Users;
+      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
+      $scope.editingGroupsList = angular.copy($scope.user.groups);
+      parsePrivileges(data.data.privileges);
+      var clusterRole = $scope.user.roles[0];
+      $scope.currentRole = clusterRole || nonRole;
+      $scope.originalRole = clusterRole || nonRole;
+      $scope.dataLoaded = true;
+    });
+  }
+
+  function parsePrivileges(rawPrivileges) {
+    var privileges = {
+      clusters: {},
+      views: {}
+    };
+    angular.forEach(rawPrivileges, function (privilege) {
+      privilege = privilege.PrivilegeInfo;
+      if (privilege.type === 'CLUSTER') {
+        // This is cluster
+        if (privileges.clusters[privilege.cluster_name]) {
+          var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
+          var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
+          // set more powerful role
+          if (curIndex < preIndex) {
             privileges.clusters[privilege.cluster_name] = privilege;
           }
-        } else if ( privilege.type === 'VIEW'){
-          privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
-          privileges.views[privilege.instance_name].version = privilege.version;
-          privileges.views[privilege.instance_name].view_name = privilege.view_name;
-          privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
-          if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) == -1) {
-            privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
-          }
+        } else {
+          privileges.clusters[privilege.cluster_name] = privilege;
         }
-      });
+      } else if (privilege.type === 'VIEW') {
+        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || {
+          privileges: [],
+          version: privilege.version,
+          view_name: privilege.view_name,
+          privilege_id: privilege.privilege_id
+        };
+        if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) === -1) {
+          privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+        }
+      }
+    });
 
-      $scope.privileges = data.data.items.length ? privileges : null;
-      $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
-      $scope.noViewPriv = $.isEmptyObject(privileges.views);
-      $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
-      $scope.dataLoaded = true;
+    $scope.privilegesView = privileges;
+    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
+    $scope.noViewPriv = $.isEmptyObject(privileges.views);
+    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
+  }
 
-    }).catch(function(data) {
-      Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
+  function loadRoles() {
+    return Cluster.getRoleOptions().then(function (data) {
+      $scope.roleOptions = data;
     });
   }
-  loadPrivileges();
+
+  loadRoles().finally(loadUserInfo);
+
 }]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
index e9ec6ab..cb25606 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
@@ -18,6 +18,6 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('UserManagementCtrl', ['$scope', function($scope) {
-  $scope.activeTab = 'USERS';
+.controller('UserManagementCtrl', ['$scope', '$routeParams', function($scope, $routeParams) {
+  $scope.activeTab = $routeParams.tab === 'groups' ? 'GROUPS' : 'USERS';
 }]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
index abe1780..00bf9c3 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UsersListCtrl.js
@@ -44,14 +44,7 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
   };
   $scope.isNotEmptyFilter = true;
 
-  $scope.pageChanged = function() {
-    $scope.loadUsers();
-  };
-  $scope.usersPerPageChanges = function() {
-    $scope.resetPagination();
-  };
-
-  $scope.loadUsers = function(){
+  function loadUsers() {
     $scope.isLoading = true;
     User.list({
       currentPage: $scope.currentPage,
@@ -59,29 +52,37 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
       searchString: $scope.filters.name,
       user_type: $scope.filters.type.value,
       active: $scope.filters.status.value
-    }).then(function(data) {
-      $scope.isLoading = false;
+    }).then(function (data) {
       $scope.totalUsers = data.data.itemTotal;
       $scope.users = data.data.items.map(User.makeUser);
       $scope.tableInfo.showed = data.data.items.length;
       $scope.tableInfo.total = data.data.itemTotal;
+    }).finally(function () {
+      $scope.isLoading = false;
     });
+  }
+
+  $scope.pageChanged = function () {
+    loadUsers();
+  };
+  $scope.usersPerPageChanges = function () {
+    $scope.resetPagination();
   };
 
-  $scope.resetPagination = function() {
+  $scope.resetPagination = function () {
     $scope.currentPage = 1;
-    $scope.loadUsers();
+    loadUsers();
   };
 
   $scope.activeFilterOptions = [
     {label: $t('common.all'), value: '*'},
     {label: $t('users.active'), value: true},
-    {label: $t('users.inactive'), value:false}
+    {label: $t('users.inactive'), value: false}
   ];
   $scope.filters.status = $scope.activeFilterOptions[0];
 
-  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
-    .concat(Object.keys(UserConstants.TYPES).map(function(key) {
+  $scope.typeFilterOptions = [{label: $t('common.all'), value: '*'}]
+    .concat(Object.keys(UserConstants.TYPES).map(function (key) {
       return {
         label: $t(UserConstants.TYPES[key].LABEL_KEY),
         value: UserConstants.TYPES[key].VALUE
@@ -97,8 +98,6 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
     $scope.resetPagination();
   };
 
-  $scope.loadUsers();
-
   $scope.$watch(
     function (scope) {
       return Boolean(scope.filters.name || (scope.filters.status && scope.filters.status.value !== '*')
@@ -109,12 +108,12 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
     }
   );
 
-  $rootScope.$watch(function(scope) {
+  $rootScope.$watch(function (scope) {
     return scope.LDAPSynced;
-  }, function(LDAPSynced) {
-    if(LDAPSynced === true){
+  }, function (LDAPSynced) {
+    if (LDAPSynced === true) {
       $rootScope.LDAPSynced = false;
-      $scope.loadUsers();
+      loadUsers();
     }
   });
 
@@ -125,10 +124,10 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
       backdrop: 'static'
     });
 
-    modalInstance.result.finally($scope.loadUsers);
+    modalInstance.result.finally(loadUsers);
   };
 
-  $scope.deleteUser = function(user) {
+  $scope.deleteUser = function (user) {
     ConfirmationModal.show(
       $t('common.delete', {
         term: $t('common.user')
@@ -137,15 +136,15 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
         instanceType: $t('common.user').toLowerCase(),
         instanceName: '"' + user.user_name + '"'
       })
-    ).then(function() {
+    ).then(function () {
       Cluster.getPrivilegesForResource({
-        nameFilter : user.user_name,
-        typeFilter : {value: 'USER'}
-      }).then(function(data) {
+        nameFilter: user.user_name,
+        typeFilter: {value: 'USER'}
+      }).then(function (data) {
         var clusterPrivilegesIds = [];
         var viewsPrivileges = [];
         if (data.items && data.items.length) {
-          angular.forEach(data.items[0].privileges, function(privilege) {
+          angular.forEach(data.items[0].privileges, function (privilege) {
             if (privilege.PrivilegeInfo.principal_type === 'USER') {
               if (privilege.PrivilegeInfo.type === 'VIEW') {
                 viewsPrivileges.push({
@@ -160,19 +159,19 @@ function($scope, User, $modal, $rootScope, UserConstants, $translate, Cluster, V
             }
           });
         }
-        User.delete(user.user_name).then(function() {
+        User.delete(user.user_name).then(function () {
           if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
+            Cluster.deleteMultiplePrivileges($rootScope.cluster.Clusters.cluster_name, clusterPrivilegesIds);
           }
-          angular.forEach(viewsPrivileges, function(privilege) {
+          angular.forEach(viewsPrivileges, function (privilege) {
             View.deletePrivilege(privilege);
           });
-          $scope.loadUsers();
+          loadUsers();
         });
       });
     });
   };
+
+  loadUsers();
+
 }]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
index de3968d..4a13e02 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/i18n.config.js
@@ -303,7 +303,7 @@ angular.module('ambariAdminConsole')
     'users.inactive': 'Inactive',
     'users.status': 'Status',
     'users.password': 'Password',
-    'users.role': 'Add roles for this user (Cluster Operator/Service Admin)',
+    'users.role': 'Add roles for this user',
     'users.confirmPassword': 'Confirm Password',
     'users.passwordConfirmation': 'Password сonfirmation',
     'users.isAmbariAdmin': 'Is this user an Ambari Admin?',
@@ -337,7 +337,7 @@ angular.module('ambariAdminConsole')
     'users.alerts.wrongPassword': 'Password must match!',
     'users.alerts.usernameRequired': 'Username Required',
     'users.alerts.cannotChange': 'Cannot Change {{term}}',
-    'users.alerts.userCreated': 'Created user <a href="#/users/{{encUserName}}">{{userName}}</a>',
+    'users.alerts.userCreated': 'Created user <a href="#/users/{{encUserName}}/edit">{{userName}}</a>',
     'users.alerts.userCreationError': 'User creation error',
     'users.alerts.removeUserError': 'Removing from group error',
     'users.alerts.cannotAddUser': 'Cannot add user to group',
@@ -373,8 +373,6 @@ angular.module('ambariAdminConsole')
     'versions.installOn': 'Install on...',
 
     'versions.register.title': 'Register Version',
-    'versions.add.title': 'Add Version',
-
     'versions.register.error.header': 'Unable to Register',
     'versions.register.error.body': 'You are attempting to register a version with a Base URL that is already in use with an existing registered version. You *must* review your Base URLs and confirm they are unique for the version you are trying to register.',
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
index 0f9b582..30ef91a 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Cluster.js
@@ -18,7 +18,11 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.factory('Cluster', ['$http', '$q', 'Settings', function($http, $q, Settings) {
+.factory('Cluster', ['$http', '$q', 'Settings', '$translate', function($http, $q, Settings, $translate) {
+  var $t = $translate.instant;
+  var permissions = null;
+  var rolesWithAuthorizations = null;
+
   return {
     repoStatusCache : {},
 
@@ -34,6 +38,13 @@ angular.module('ambariAdminConsole')
 
     ineditableRoles : ['VIEW.USER', 'AMBARI.ADMINISTRATOR'],
 
+    sortRoles: function(roles) {
+      var orderedRoles = ['AMBARI.ADMINISTRATOR'].concat(this.orderedRoles);
+      return roles.sort(function(a, b) {
+        return orderedRoles.indexOf(a.permission_name) - orderedRoles.indexOf(b.permission_name);
+      });
+    },
+
     getAllClusters: function() {
       var deferred = $q.defer();
       $http.get(Settings.baseUrl + '/clusters?fields=Clusters/cluster_id', {mock: 'cluster/clusters.json'})
@@ -120,22 +131,48 @@ angular.module('ambariAdminConsole')
 
       return deferred.promise;
     },
+    getRoleOptions: function () {
+      var roleOptions = [];
+      var deferred = $q.defer();
+      var localDeferred = $q.defer();
+      var promise = permissions ? localDeferred.promise : this.getPermissions();
+
+      localDeferred.resolve(permissions);
+      promise.then(function(data) {
+        permissions = data;
+        roleOptions = data.map(function(item) {
+          return item.PermissionInfo;
+        });
+        roleOptions.unshift({
+          permission_name: 'NONE',
+          permission_label: $t('users.roles.none')
+        });
+      }).finally(function() {
+        deferred.resolve(roleOptions);
+      });
+      return deferred.promise;
+    },
     getRolesWithAuthorizations: function() {
-      var self = this;
       var deferred = $q.defer();
-      $http({
-        method: 'GET',
-        url: Settings.baseUrl + '/permissions?PermissionInfo/resource_name.in(CLUSTER,AMBARI)',
-        mock: 'permission/permissions.json',
-        params: {
-          fields: 'PermissionInfo/*,authorizations/AuthorizationInfo/*'
-        }
-      })
-        .success(function(data) {
-          deferred.resolve(data.items);
+      if (rolesWithAuthorizations) {
+        deferred.resolve(rolesWithAuthorizations);
+      } else {
+        $http({
+          method: 'GET',
+          url: Settings.baseUrl + '/permissions?PermissionInfo/resource_name.in(CLUSTER,AMBARI)',
+          mock: 'permission/permissions.json',
+          params: {
+            fields: 'PermissionInfo/*,authorizations/AuthorizationInfo/*'
+          }
         })
-        .catch(function(data) {
-          deferred.reject(data); });
+          .success(function (data) {
+            rolesWithAuthorizations = data.items;
+            deferred.resolve(data.items);
+          })
+          .catch(function (data) {
+            deferred.reject(data);
+          });
+      }
 
       return deferred.promise;
     },
@@ -159,31 +196,6 @@ angular.module('ambariAdminConsole')
 
       return deferred.promise;
     },
-    getPrivilegesWithFilters: function(params) {
-      var deferred = $q.defer();
-      var isUser = params.typeFilter.value == 'USER';
-      var endpoint = isUser? '/users' : '/groups';
-      var nameURL = isUser? '&Users/user_name.matches(.*' : '&Groups/group_name.matches(.*';
-      var nameFilter = params.nameFilter? nameURL + params.nameFilter + '.*)' : '';
-      var roleFilter = params.roleFilter.value? '&privileges/PrivilegeInfo/permission_name.matches(.*' + params.roleFilter.value + '.*)' : '';
-      $http({
-        method: 'GET',
-        url: Settings.baseUrl + endpoint + '?'
-        + 'fields=privileges/PrivilegeInfo/*'
-        + nameFilter
-        + roleFilter
-        + '&from=' + (params.currentPage - 1) * params.usersPerPage
-        + '&page_size=' + params.usersPerPage
-      })
-      .success(function(data) {
-        deferred.resolve(data);
-      })
-      .catch(function(data) {
-        deferred.reject(data);
-      });
-
-      return deferred.promise;
-    },
     getPrivilegesForResource: function(params) {
       var deferred = $q.defer();
       var isUser = (params.typeFilter.value == 'USER');

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
index f52a7e5..0509e11 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Group.js
@@ -18,49 +18,29 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.factory('Group', ['$http', '$q', 'Settings', 'GroupConstants', '$translate', function($http, $q, Settings, GroupConstants, $translate) {
+.factory('Group', ['$http', '$q', 'Settings', '$translate', 'Cluster', function($http, $q, Settings, $translate, Cluster) {
   var $t = $translate.instant;
-  function Group(item){
-    if(typeof item === 'string'){
-      this.group_name = item;
-    } else if(typeof item === 'object'){
-      angular.extend(this, item.Groups);
-      this.getMembers();
+  var types = {
+    LOCAL: {
+      VALUE: 'LOCAL',
+      LABEL_KEY: 'common.local'
+    },
+    PAM: {
+      VALUE: 'PAM',
+      LABEL_KEY: 'common.pam'
+    },
+    LDAP: {
+      VALUE: 'LDAP',
+      LABEL_KEY: 'common.ldap'
     }
-  }
+  };
 
-  Group.prototype.isLDAP = function() {
-    var deferred = $q.defer();
-    var self = this;
-    if( typeof this.ldap_group === 'boolean' ){
-      deferred.resolve(this.ldap_group)
-    } else {
-      $http({
-        method: 'GET',
-        url: Settings.baseUrl + '/groups/'+this.group_name
-      }).
-      success(function(data) {
-        self.ldap_group = data.Groups.ldap_group;
-        deferred.resolve(self.ldap_group);
-      });
+  function Group(item) {
+    if (typeof item === 'string') {
+      this.group_name = item;
+    } else if (typeof item === 'object') {
+      angular.extend(this, item.Groups);
     }
-
-    return deferred.promise;
-  }
-
-  Group.prototype.getGroupType = function() {
-    var deferred = $q.defer();
-    var self = this;
-    $http({
-      method: 'GET',
-      url: Settings.baseUrl + '/groups/'+this.group_name
-    }).
-    success(function(data) {
-      self.group_type = data.Groups.group_type;
-      deferred.resolve(self.group_type);
-    });
-
-    return deferred.promise;
   }
 
   Group.prototype.save = function() {
@@ -86,28 +66,6 @@ angular.module('ambariAdminConsole')
     return deferred.promise;
   };
 
-  Group.prototype.getMembers = function() {
-    var deferred = $q.defer();
-    var self = this;
-
-    $http({
-      method: 'GET',
-      url: Settings.baseUrl + '/groups/' + this.group_name + '/members'
-    })
-    .success(function(data) {
-      self.members = [];
-      angular.forEach(data.items, function(member) {
-        self.members.push(member.MemberInfo.user_name);
-      });
-      deferred.resolve(self.members);
-    })
-    .error(function(data) {
-      deferred.reject(data);
-    });
-
-    return deferred.promise;
-  };
-
   Group.prototype.saveMembers = function() {
     var self = this;
     var deferred = $q.defer();
@@ -132,27 +90,6 @@ angular.module('ambariAdminConsole')
       deferred.reject(data);
     });
     return deferred.promise;
-  }
-
-  Group.prototype.addMember = function(memberName) {
-    var deferred = $q.defer();
-
-    $http({
-      method: 'POST',
-      url: Settings.baseUrl + '/groups/' + this.group_name + '/members' + '/'+ encodeURIComponent(member.user_name)
-    })
-    .success(function(data) {
-      deferred.resolve(data)
-    })
-    .error(function(data) {
-      deferred.reject(data);
-    });
-
-    return deferred.promise;
-  };
-
-  Group.prototype.removeMember = function(memberId) {
-    return $http.delete(Settings.baseUrl + '/groups/'+this.group_name+'/members/'+memberId);
   };
 
   Group.removeMemberFromGroup = function(groupName, memberName) {
@@ -174,14 +111,8 @@ angular.module('ambariAdminConsole')
       + (params.group_type === '*' ? '' : '&Groups/group_type=' + params.group_type)
     )
     .success(function(data) {
-      var groups = [];
-      if(Array.isArray(data.items)){
-        angular.forEach(data.items, function(item) {
-          groups.push(new Group(item));
-        });
-      }
-      groups.itemTotal = data.itemTotal;
-      deferred.resolve(groups);
+      data.items.itemTotal = data.itemTotal;
+      deferred.resolve(data.items);
     })
     .error(function(data) {
       deferred.reject(data);
@@ -204,6 +135,23 @@ angular.module('ambariAdminConsole')
     });
   };
 
+  Group.get = function (group_name) {
+    var deferred = $q.defer();
+    $http({
+      method: 'GET',
+      url: Settings.baseUrl + '/groups/' + group_name +
+      '?fields=Groups,privileges/PrivilegeInfo/*,members/MemberInfo'
+    }).success(function (data) {
+      deferred.resolve(Group.makeGroup(data));
+    });
+
+    return deferred.promise;
+  };
+
+  Group.getTypes = function () {
+    return types;
+  };
+
   /**
      * Generate group info to display by response data from API.
      * Generally this is a single point to manage all required and useful data
@@ -212,9 +160,19 @@ angular.module('ambariAdminConsole')
      * @param {Object} group - object from API response
      * @returns {Object}
      */
-   Group.makeGroup = function(group) {
-      group.groupTypeName = $t(GroupConstants.TYPES[group.group_type].LABEL_KEY);
-      return group;
+  Group.makeGroup = function(data) {
+    var group = new Group(data.Groups.group_name);
+    group.groupTypeName = $t(types[data.Groups.group_type].LABEL_KEY);
+    group.group_type = data.Groups.group_type;
+    group.ldap_group = data.Groups.ldap_group;
+    group.privileges = data.privileges;
+    group.members = data.members;
+    group.roles = Cluster.sortRoles(data.privileges.filter(function(item) {
+      return item.PrivilegeInfo.type === 'CLUSTER' || item.PrivilegeInfo.type === 'AMBARI';
+    }).map(function(item) {
+      return item.PrivilegeInfo;
+    }));
+    return group;
   };
 
   return Group;

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/GroupConstants.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/GroupConstants.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/GroupConstants.js
deleted file mode 100644
index 42e8d73..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/GroupConstants.js
+++ /dev/null
@@ -1,38 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole').constant('GroupConstants', {
-  /**
-   * Available group_types 'values' and 'labels' map.
-   */
-  TYPES: {
-    LOCAL: {
-      VALUE: 'LOCAL',
-      LABEL_KEY: 'common.local'
-    },
-    PAM: {
-      VALUE: 'PAM',
-      LABEL_KEY: 'common.pam'
-    },
-    LDAP: {
-      VALUE: 'LDAP',
-      LABEL_KEY: 'common.ldap'
-    }
-  }
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
index 06019c2..7b01116 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/RoleDetailsModal.js
@@ -22,11 +22,10 @@ angular.module('ambariAdminConsole')
   return {
     show: function(roles) {
       roles = roles.map(function(role) {
-        role.authorizations = role.authorizations.map(function(authorization) {
+        var r = role.PermissionInfo;
+        r.authorizations = role.authorizations.map(function(authorization) {
           return authorization.AuthorizationInfo;
         });
-        var r = role.PermissionInfo;
-        r.authorizations = role.authorizations;
         return r;
       });
       var modalInstance = $modal.open({

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
index 47015d1..7932d9b 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/User.js
@@ -18,7 +18,7 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-  .factory('User', ['Restangular', '$http', 'Settings', 'UserConstants', '$translate', function(Restangular, $http, Settings, UserConstants, $translate) {
+.factory('User', ['Restangular', '$http', 'Settings', 'UserConstants', '$translate', 'Cluster', function(Restangular, $http, Settings, UserConstants, $translate, Cluster) {
   Restangular.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
     var extractedData;
     if(operation === 'getList'){
@@ -31,14 +31,13 @@ angular.module('ambariAdminConsole')
     return extractedData;
   });
   var $t = $translate.instant;
-  var Users = Restangular.all('users');
 
   return {
     list: function(params) {
       return $http.get(
         Settings.baseUrl + '/users/?'
         + 'Users/user_name.matches(.*'+params.searchString+'.*)'
-        + '&fields=*'
+        + '&fields=privileges/PrivilegeInfo/*,Users'
         + '&from=' + (params.currentPage-1)*params.usersPerPage
         + '&page_size=' + params.usersPerPage
         + (params.user_type === '*' ? '' : '&Users/user_type=' + params.user_type)
@@ -53,6 +52,12 @@ angular.module('ambariAdminConsole')
         + '&from=0&page_size=20'
       );
     },
+    getWithRoles: function(userId) {
+      return $http.get(
+        Settings.baseUrl + '/users/' + userId
+        + '?fields=privileges/PrivilegeInfo,Users'
+      );
+    },
     get: function(userId) {
       return Restangular.one('users', userId).get();
     },
@@ -97,7 +102,11 @@ angular.module('ambariAdminConsole')
       user.Users.encodedName = encodeURIComponent(user.Users.user_name);
       user.Users.userTypeName = $t(UserConstants.TYPES[user.Users.user_type].LABEL_KEY);
       user.Users.ldapUser = user.Users.user_type === UserConstants.TYPES.LDAP.VALUE;
-      user.Users.role = user.privileges.length ? user.privileges[0].PrivilegeInfo.privilege_id : null;
+      user.Users.roles = Cluster.sortRoles(user.privileges.filter(function(item) {
+        return item.PrivilegeInfo.type === 'CLUSTER' || item.PrivilegeInfo.type === 'AMBARI';
+      }).map(function(item) {
+        return item.PrivilegeInfo;
+      }));
 
       return user;
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
index 91b2fb1..b4aa558 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/main.css
@@ -312,11 +312,6 @@ a.gotoinstance{
   font-size: 16px;
 }
 
-.user-edit-panel .ats-switch span.switch-right , .create-user-form .ats-switch span.switch-right, .enable-ldap .ats-switch span.switch-right {
-  background-color: #da4f49;
-  color: white;
-}
-
 .create-view-form, .register-version-form, .edit-version-form {
   padding-bottom: 50px;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
index 77c94ac..3c9756e 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/user-management.css
@@ -28,3 +28,16 @@
 #user-management .groups-pane {
   margin-top: -35px;
 }
+
+#group-edit .roles-label,
+#user-edit .roles-label {
+  line-height: 30px;
+}
+
+#create-user-form .roles-label i,
+#create-group-form .roles-label i,
+#group-edit .roles-label i,
+#user-edit .roles-label i {
+  margin-right: -10px;
+  cursor: pointer;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/remoteClusters/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/remoteClusters/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/remoteClusters/list.html
index 8bb6632..59d8acb 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/remoteClusters/list.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/remoteClusters/list.html
@@ -18,10 +18,7 @@
 
 <div class="users-pane">
   <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li class="active">{{'common.remoteClusters' | translate}}</li>
-    </ol>
-    <div class="pull-right top-margin-4">
+    <div class="pull-right">
       <a href="#/remoteClusters/create" class="btn btn-default">
         {{'views.registerRemoteCluster' | translate}}
       </a>

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
index a411640..cf5c516 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/stackVersions/list.html
@@ -18,12 +18,9 @@
 
 <div id="stack-versions">
   <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li class="active">{{'common.versions' | translate}}</li>
-    </ol>
-    <div class="pull-right top-margin-4">
+    <div class="pull-right">
       <a href="#/stackVersions/create" class="btn btn-default">
-        {{'versions.add.title' | translate}}
+        {{'versions.register.title' | translate}}
       </a>
     </div>
   </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
index 90a1907..5656417 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/groupEdit.html
@@ -16,84 +16,107 @@
 * limitations under the License.
 -->
 
-<div class="clearfix">
-  <div class="pull-right">
-    <div ng-switch="group.group_type != 'LOCAL'">
-      <button
-        ng-switch-when="true"
-        class="btn disabled deletegroup-btn"
-        tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">
-        {{'common.delete' | translate: '{term: constants.group}'}}
-      </button>
-      <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">
-        {{'common.delete' | translate: '{term: constants.group}'}}
-      </button>
+<div id="group-edit">
+  <div class="clearfix">
+    <ol class="breadcrumb pull-left">
+      <li><a href="#/userManagement?tab=groups">{{'common.groups' | translate}}</a></li>
+      <li class="active">{{group.group_name}}</li>
+    </ol>
+    <div class="pull-right">
+      <div ng-switch="group.group_type != 'LOCAL'">
+        <button
+          ng-switch-when="true"
+          class="btn disabled deletegroup-btn"
+          tooltip="{{'common.cannotDelete' | translate: '{term: constants.group}'}}">
+          {{'common.delete' | translate: '{term: constants.group}'}}
+        </button>
+        <button ng-switch-when="false" class="btn btn-danger deletegroup-btn" ng-click="deleteGroup(group)">
+          {{'common.delete' | translate: '{term: constants.group}'}}
+        </button>
+      </div>
     </div>
   </div>
-</div>
-<form class="form-horizontal group-edit" role="form" novalidate name="form" >
-  <div class="form-group">
-    <label class="col-sm-2 control-label">{{'common.type' | translate}}</label>
-    <div class="col-sm-10">
-      <label class="control-label">{{group.groupTypeName | translate}}</label>
+
+  <form class="form-horizontal" role="form" novalidate name="form" >
+    <div class="form-group">
+      <label class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+      <div class="col-sm-10">
+        <label class="control-label">{{group.groupTypeName | translate}}</label>
+      </div>
     </div>
-  </div>
-  <div class="form-group">
-    <label class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
-    <div class="col-sm-10">
-      <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
+    <div class="form-group">
+      <label class="col-sm-2 control-label">{{group.groupTypeName | translate}} {{'groups.members' | translate}}</label>
+      <div class="col-sm-10">
+        <editable-list items-source="group.editingUsers" resource-type="User" editable="group.group_type == 'LOCAL'"></editable-list>
+      </div>
     </div>
-  </div>
-
-  <div class="form-group">
+    <div class="form-group">
+      <label for="role" class="col-sm-2 roles-label">
+        {{'groups.role' | translate}}
+        <i class="fa fa-question-circle" aria-hidden="true" ng-click="showHelpPage()"></i>
+      </label>
+      <div class="col-sm-3">
+        <select class="form-control"
+                id="role"
+                name="role"
+                ng-change="updateRole()"
+                ng-options="item as item.permission_label for item in roleOptions track by item.permission_name"
+                ng-model="currentRole">
+        </select>
+      </div>
+    </div>
+    <div class="form-group">
       <label class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
       <div class="col-sm-10">
         <table class="table" ng-hide="hidePrivileges">
           <thead>
-            <tr>
-              <th>{{'common.cluster' | translate}}</th>
-              <th>{{'common.clusterRole' | translate}}</th>
-            </tr>
+          <tr>
+            <th>{{'common.cluster' | translate}}</th>
+            <th>{{'common.clusterRole' | translate}}</th>
+          </tr>
           </thead>
           <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.clusters">
-              <td>
-                <span class="glyphicon glyphicon-cloud"></span> 
-                <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
-              </td>
-              <td>
-                <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
-              </td>
-            </tr>
-            <tr>
-              <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
-            </tr>
+          <tr ng-repeat="(name, privilege) in privileges.clusters">
+            <td>
+              <span class="glyphicon glyphicon-cloud"></span>
+              <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
+            </td>
+            <td>
+              <span tooltip="{{item}}" ng-repeat="item in privilege">{{item | translate}}{{$last ? '' : ', '}}</span>
+            </td>
+          </tr>
+          <tr>
+            <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
+          </tr>
           </tbody>
           <thead class="view-permission-header">
-            <tr>
-              <th>{{'common.view' | translate}}</th>
-              <th>{{'common.viewPermissions' | translate}}</th>
-            </tr>
+          <tr>
+            <th>{{'common.view' | translate}}</th>
+            <th>{{'common.viewPermissions' | translate}}</th>
+          </tr>
           </thead>
           <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.views">
-              <td>
-                <span class="glyphicon glyphicon-th"></span>
-                <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
-              </td>
-              <td>
-                <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
-              </td>
-              <td>
-                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
-              </td>
-            </tr>
-            <tr>
-              <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
-            </tr>
+          <tr ng-repeat="(name, privilege) in privileges.views">
+            <td>
+              <span class="glyphicon glyphicon-th"></span>
+              <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
+            </td>
+            <td>
+              <span tooltip="{{item}}" ng-repeat="item in privilege.privileges">{{item | translate}}{{$last ? '' : ', '}}</span>
+            </td>
+            <td>
+              <i class="fa fa-trash-o" aria-hidden="true" ng-click="removeViewPrivilege(name, privilege);"></i>
+            </td>
+          </tr>
+          <tr>
+            <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
+          </tr>
           </tbody>
         </table>
-        <div class="alert alert-info hide-soft" ng-class="{'visible' : !privileges}">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}</div>
+        <div class="alert alert-info" ng-show="hidePrivileges">
+          {{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.group.toLowerCase()}'}}
+        </div>
       </div>
     </div>
-</form>
+  </form>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
index 079eefb..8520fc2 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/main.html
@@ -19,10 +19,10 @@
 <div id="user-management">
   <ul class="nav nav-tabs">
     <li ng-class="{active: activeTab === 'USERS'}">
-      <a ng-click="activeTab = 'USERS'">{{'common.users' | translate}}</a>
+      <a href="#/userManagement?tab=users" >{{'common.users' | translate}}</a>
     </li>
     <li ng-class="{active: activeTab === 'GROUPS'}">
-      <a ng-click="activeTab = 'GROUPS'">{{'common.groups' | translate}}</a>
+      <a href="#/userManagement?tab=groups" >{{'common.groups' | translate}}</a>
     </li>
   </ul>
   <div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
index e0c1144..e11b478 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
@@ -60,17 +60,17 @@
     <div class="row">
       <div class="form-group col-sm-6"
            ng-class="{ 'has-error': form.groupCreateForm.role.$error.required && form.groupCreateForm.submitted }">
-        <label for="role" class="nowrap">
+        <label for="role" class="nowrap roles-label">
           {{'groups.role' | translate}}
-          <i class="fa fa-question-circle" aria-hidden="true"></i>
+          <i class="fa fa-question-circle" aria-hidden="true" ng-click="showHelpPage()"></i>
         </label>
         <select
           class="form-control"
           id="role"
           name="role"
           ng-model="formData.role">
-          <option value="" disabled selected>{{'common.select' | translate}}</option>
-          <option ng-repeat="role in roleOptions" value="{{role.permission_id}}">{{role.permission_label}}</option>
+          <option value="" class="hide">{{'common.select' | translate}}</option>
+          <option ng-repeat="role in roleOptions" value="{{role.permission_name}}">{{role.permission_label}}</option>
         </select>
         <span class="help-block validation-block" ng-show='form.groupCreateForm.role.$error.required && form.groupCreateForm.submitted'>
           {{'common.alerts.fieldRequired' | translate}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
index 0af26eb..2a71102 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
@@ -100,9 +100,9 @@
     <div class="row">
       <div class="form-group col-sm-6"
            ng-class="{ 'has-error': form.userCreateForm.role.$error.required && form.userCreateForm.submitted }">
-        <label for="role" class="nowrap">
-          {{'users.role' | translate}}<span>&nbsp;*</span>&nbsp;
-          <i class="fa fa-question-circle" aria-hidden="true"></i>
+        <label for="role" class="nowrap roles-label">
+          {{'users.role' | translate}}<span>&nbsp;*</span>
+          <i class="fa fa-question-circle" aria-hidden="true" ng-click="showHelpPage()"></i>
         </label>
         <select
           class="form-control"
@@ -110,8 +110,8 @@
           name="role"
           ng-model="formData.role"
           required>
-          <option value="" disabled selected>{{'common.select' | translate}}</option>
-          <option ng-repeat="role in roleOptions" value="{{role.permission_id}}">{{role.permission_label}}</option>
+          <option value="" class="hide">{{'common.select' | translate}}</option>
+          <option ng-repeat="role in roleOptions" value="{{role.permission_name}}">{{role.permission_label}}</option>
         </select>
         <span class="help-block validation-block" ng-show='form.userCreateForm.role.$error.required && form.userCreateForm.submitted'>
           {{'common.alerts.fieldRequired' | translate}}


[05/50] [abbrv] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
new file mode 100644
index 0000000..fcafa59
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
@@ -0,0 +1,344 @@
+/**
+ * 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.
+ */
+
+describe('#Cluster', function () {
+
+  describe('UsersListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('UsersListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.filters.name = 'a';
+        scope.filters.status = {
+          label: $t('common.local'),
+          value: false
+        };
+        scope.filters.type = {
+          label: $t('common.local'),
+          value: 'LOCAL'
+        };
+        scope.clearFilters();
+        expect(scope.filters.name).toEqual('');
+        expect(scope.filters.status).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.filters.type).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          currentActiveFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'activity filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'name and activity filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and admin filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters with "0" as string'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'name and activity filters with "0" as string'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and admin filters with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'type and activity filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'type and admin filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'activity and admin filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except name one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except type one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except activity one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except admin one'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string except type one'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string except activity one'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string except admin one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: false
+          },
+          currentActiveFilter: {
+            value: 'LOCAL'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: false
+          },
+          currentActiveFilter: {
+            value: 'LOCAL'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
+          scope.filters.name = item.currentNameFilter;
+          scope.filters.status = item.currentActiveFilter;
+          scope.filters.type = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
deleted file mode 100644
index 9d6cd54..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
+++ /dev/null
@@ -1,383 +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.
- */
-
-describe('#Cluster', function () {
-
-  describe('UsersListCtrl', function() {
-
-    var scope, ctrl, $t, $httpBackend;
-
-    beforeEach(module('ambariAdminConsole', function () {}));
-
-    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
-      scope = $rootScope.$new();
-      $t = _$translate_.instant;
-      $httpBackend = _$httpBackend_;
-      ctrl = $controller('UsersListCtrl', {
-        $scope: scope
-      });
-    }));
-
-    describe('#clearFilters()', function () {
-
-      it('should clear filters and reset pagination', function () {
-        scope.currentPage = 2;
-        scope.currentNameFilter = 'a';
-        scope.currentActiveFilter = {
-          label: $t('common.local'),
-          value: false
-        };
-        scope.currentTypeFilter = {
-          label: $t('common.local'),
-          value: 'LOCAL'
-        };
-        scope.adminFilter = true;
-        scope.clearFilters();
-        expect(scope.currentNameFilter).toEqual('');
-        expect(scope.currentActiveFilter).toEqual({
-          label: $t('common.all'),
-          value: '*'
-        });
-        expect(scope.currentTypeFilter).toEqual({
-          label: $t('common.all'),
-          value: '*'
-        });
-        expect(scope.currentPage).toEqual(1);
-        expect(scope.adminFilter).toBe(false);
-      });
-
-    });
-
-    describe('#isNotEmptyFilter', function () {
-
-      var cases = [
-        {
-          currentNameFilter: '',
-          currentTypeFilter: null,
-          currentActiveFilter: null,
-          isNotEmptyFilter: false,
-          adminFilter: false,
-          title: 'no filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: false,
-          title: 'empty filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name filter'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name filter with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'type filter'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'activity filter'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'admin filter'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and type filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and activity filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'name and admin filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and type filters with "0" as string'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and activity filters with "0" as string'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'name and admin filters with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'type and activity filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'type and admin filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'activity and admin filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters except name one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters except type one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters except activity one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'all filters except admin one'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string except type one'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string except activity one'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string except admin one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: false
-          },
-          currentActiveFilter: {
-            value: 'LOCAL'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: false
-          },
-          currentActiveFilter: {
-            value: 'LOCAL'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string'
-        }
-      ];
-
-      cases.forEach(function (item) {
-        it(item.title, function () {
-          $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
-          scope.currentNameFilter = item.currentNameFilter;
-          scope.currentActiveFilter = item.currentActiveFilter;
-          scope.currentTypeFilter = item.currentTypeFilter;
-          scope.adminFilter = item.adminFilter;
-          scope.$digest();
-          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
-        });
-      });
-
-    });
-
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
index 1b76dcf..7f67de4 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
@@ -25,7 +25,13 @@ describe('Utility Service', function () {
 
   beforeEach(function () {
     module('ambariAdminConsole', function ($provide) {
-      $provide.value('$window', {});
+      $provide.value('$window', {
+        localStorage: {
+          getItem: function() {return '{}';},
+          setItem: function() {}
+        },
+        location: {}
+      });
     });
     inject(function (_Utility_, _$httpBackend_, $rootScope, $controller, _Cluster_, _$q_) {
       Utility = _Utility_;
@@ -54,7 +60,7 @@ describe('Utility Service', function () {
       httpBackend.whenGET(/\/api\/v1\/views.+/).respond(200, {
         items: []
       });
-      httpBackend.whenGET("views/clusterInformation.html").respond(200, {});
+      httpBackend.whenGET("views/clusters/clusterInformation.html").respond(200, {});
     });
   });
 


[09/50] [abbrv] ambari git commit: AMBARI-22513 Make yumrpm.py functions to use global defined commands (dgrinenko)

Posted by ao...@apache.org.
AMBARI-22513 Make yumrpm.py functions to use global defined commands (dgrinenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/02490734
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/02490734
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/02490734

Branch: refs/heads/branch-3.0-perf
Commit: 0249073469de5cd11f032705d609f8cb19ff28c0
Parents: 99b19e5
Author: Dmytro Grinenko <ha...@apache.org>
Authored: Fri Nov 24 16:41:12 2017 +0200
Committer: Dmytro Grinenko <ha...@apache.org>
Committed: Fri Nov 24 16:41:12 2017 +0200

----------------------------------------------------------------------
 .../core/providers/package/yumrpm.py                    |  4 ++--
 .../HIVE/0.12.0.2.0/package/scripts/hive.py             | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/02490734/ambari-common/src/main/python/resource_management/core/providers/package/yumrpm.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/core/providers/package/yumrpm.py b/ambari-common/src/main/python/resource_management/core/providers/package/yumrpm.py
index 8426479..367e2af 100644
--- a/ambari-common/src/main/python/resource_management/core/providers/package/yumrpm.py
+++ b/ambari-common/src/main/python/resource_management/core/providers/package/yumrpm.py
@@ -138,7 +138,7 @@ class YumProvider(RPMBasedPackageProvider):
     :rtype list[list,]
     """
 
-    cmd = [AMBARI_SUDO_BINARY, "yum", "list", "available"]
+    cmd = list(ALL_AVAILABLE_PACKAGES_CMD)
 
     if repo_filter:
       cmd.extend(["--disablerepo=*", "--enablerepo=" + repo_filter])
@@ -154,7 +154,7 @@ class YumProvider(RPMBasedPackageProvider):
     :rtype list[list,]
     """
 
-    packages = self._lookup_packages([AMBARI_SUDO_BINARY, "yum", "list", "installed"], "Installed Packages")
+    packages = self._lookup_packages(list(ALL_INSTALLED_PACKAGES_CMD), "Installed Packages")
     if repo_filter:
       packages = [item for item in packages if item[2].lower() == repo_filter.lower()]
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/02490734/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive.py b/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive.py
index 716a37c..d9cc55f 100644
--- a/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive.py
+++ b/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive.py
@@ -24,7 +24,7 @@ from urlparse import urlparse
 
 from resource_management.libraries.script.script import Script
 from resource_management.libraries.resources.hdfs_resource import HdfsResource
-from resource_management.libraries.functions.copy_tarball import copy_to_hdfs
+from resource_management.libraries.functions import copy_tarball
 from resource_management.libraries.functions.get_config import get_config
 from resource_management.libraries.functions import StackFeature
 from resource_management.libraries.functions.stack_features import check_stack_feature
@@ -177,19 +177,19 @@ def setup_hiveserver2():
   # *********************************
   #  if copy tarball to HDFS feature  supported copy mapreduce.tar.gz and tez.tar.gz to HDFS
   if params.stack_version_formatted_major and check_stack_feature(StackFeature.COPY_TARBALL_TO_HDFS, params.stack_version_formatted_major):
-    copy_to_hdfs("mapreduce", params.user_group, params.hdfs_user, skip=params.sysprep_skip_copy_tarballs_hdfs)
-    copy_to_hdfs("tez", params.user_group, params.hdfs_user, skip=params.sysprep_skip_copy_tarballs_hdfs)
+    copy_tarball.copy_to_hdfs("mapreduce", params.user_group, params.hdfs_user, skip=params.sysprep_skip_copy_tarballs_hdfs)
+    copy_tarball.copy_to_hdfs("tez", params.user_group, params.hdfs_user, skip=params.sysprep_skip_copy_tarballs_hdfs)
 
   # Always copy pig.tar.gz and hive.tar.gz using the appropriate mode.
   # This can use a different source and dest location to account
-  copy_to_hdfs("pig",
+  copy_tarball.copy_to_hdfs("pig",
                params.user_group,
                params.hdfs_user,
                file_mode=params.tarballs_mode,
                custom_source_file=params.pig_tar_source,
                custom_dest_file=params.pig_tar_dest_file,
                skip=params.sysprep_skip_copy_tarballs_hdfs)
-  copy_to_hdfs("hive",
+  copy_tarball.copy_to_hdfs("hive",
                params.user_group,
                params.hdfs_user,
                file_mode=params.tarballs_mode,
@@ -210,7 +210,7 @@ def setup_hiveserver2():
       src_filename = os.path.basename(source_file)
       dest_file = os.path.join(dest_dir, src_filename)
 
-      copy_to_hdfs(tarball_name,
+      copy_tarball.copy_to_hdfs(tarball_name,
                    params.user_group,
                    params.hdfs_user,
                    file_mode=params.tarballs_mode,


[04/50] [abbrv] ambari git commit: AMBARI-21569.Users randomly getting "HDFS020 Could not write file" exceptions while running query from Hive View(Venkata Sairam)

Posted by ao...@apache.org.
AMBARI-21569.Users randomly getting "HDFS020 Could not write file" exceptions while running query from Hive View(Venkata Sairam)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/8e36662a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/8e36662a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/8e36662a

Branch: refs/heads/branch-3.0-perf
Commit: 8e36662ae1dffe7cb637b3d1edb38278f0111012
Parents: 5136021
Author: Venkata Sairam <ve...@gmail.com>
Authored: Thu Nov 23 15:48:52 2017 +0530
Committer: Venkata Sairam <ve...@gmail.com>
Committed: Thu Nov 23 15:48:52 2017 +0530

----------------------------------------------------------------------
 .../org/apache/ambari/view/utils/hdfs/HdfsApi.java | 16 +++++++++++++++-
 .../apache/ambari/view/utils/hdfs/HdfsUtil.java    | 17 ++++++++++++-----
 2 files changed, 27 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/8e36662a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsApi.java
----------------------------------------------------------------------
diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsApi.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsApi.java
index 3db2081..812cd54 100644
--- a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsApi.java
+++ b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsApi.java
@@ -485,7 +485,20 @@ public class HdfsApi {
    * @throws IOException
    * @throws InterruptedException
    */
-  public <T> T execute(PrivilegedExceptionAction<T> action)
+  public <T> T execute(PrivilegedExceptionAction<T> action) throws IOException, InterruptedException {
+    return this.execute(action, false);
+  }
+
+
+  /**
+   * Executes action on HDFS using doAs
+   * @param action strategy object
+   * @param <T> result type
+   * @return result of operation
+   * @throws IOException
+   * @throws InterruptedException
+   */
+  public <T> T execute(PrivilegedExceptionAction<T> action, boolean alwaysRetry)
       throws IOException, InterruptedException {
     T result = null;
 
@@ -508,6 +521,7 @@ public class HdfsApi {
         }
         LOG.info("HDFS threw 'IOException: Cannot obtain block length' exception. " +
             "Retrying... Try #" + (tryNumber + 1));
+        LOG.error("Retrying: " + ex.getMessage(),ex);
         Thread.sleep(1000);  //retry after 1 second
       }
     } while (!succeeded);

http://git-wip-us.apache.org/repos/asf/ambari/blob/8e36662a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsUtil.java
----------------------------------------------------------------------
diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsUtil.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsUtil.java
index 0670f1a..810129b 100644
--- a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsUtil.java
+++ b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/hdfs/HdfsUtil.java
@@ -27,6 +27,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Map;
 
 public class HdfsUtil {
@@ -38,13 +39,19 @@ public class HdfsUtil {
    * @param filePath path to file
    * @param content new content of file
    */
-  public static void putStringToFile(HdfsApi hdfs, String filePath, String content) throws HdfsApiException {
-    FSDataOutputStream stream;
+  public static void putStringToFile(final HdfsApi hdfs,final String filePath, final String content) throws HdfsApiException {
+
     try {
       synchronized (hdfs) {
-        stream = hdfs.create(filePath, true);
-        stream.write(content.getBytes());
-        stream.close();
+        hdfs.execute(new PrivilegedExceptionAction<Void>() {
+          @Override
+          public Void run() throws Exception {
+            final FSDataOutputStream stream = hdfs.create(filePath, true);
+            stream.write(content.getBytes());
+            stream.close();
+            return null;
+          }
+        }, true);
       }
     } catch (IOException e) {
       throw new HdfsApiException("HDFS020 Could not write file " + filePath, e);


[15/50] [abbrv] ambari git commit: AMBARI-22522 - Livy server fails to start during downgrade due to absence of 'conf' directory (jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22522 - Livy server fails to start during downgrade due to absence of 'conf' directory (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1d9985cf
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1d9985cf
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1d9985cf

Branch: refs/heads/branch-3.0-perf
Commit: 1d9985cf5727bd4b8085ee0afe477b759875b348
Parents: 32e25b8
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon Nov 27 09:03:23 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Mon Nov 27 12:04:02 2017 -0500

----------------------------------------------------------------------
 .../main/resources/stacks/HDP/2.0.6/properties/stack_packages.json | 2 +-
 .../main/resources/stacks/HDP/3.0/properties/stack_packages.json   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1d9985cf/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
index 245449c..794d2b0 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
@@ -1069,7 +1069,7 @@
       "livy": [
         {
           "conf_dir": "/etc/livy/conf",
-          "current_dir": "{0}/current/livy"
+          "current_dir": "{0}/current/livy-client/conf"
         }
       ],
       "mahout": [

http://git-wip-us.apache.org/repos/asf/ambari/blob/1d9985cf/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
index 5603c0c..5fb61c8 100644
--- a/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
+++ b/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
@@ -946,7 +946,7 @@
       "livy": [
         {
           "conf_dir": "/etc/livy/conf",
-          "current_dir": "{0}/current/livy"
+          "current_dir": "{0}/current/livy-client/conf"
         }
       ],
       "mahout": [


[45/50] [abbrv] ambari git commit: AMBARI-22479 After removing force_delete_components option hosts are not deleted (dsen)

Posted by ao...@apache.org.
AMBARI-22479 After removing force_delete_components option hosts are not deleted (dsen)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1f7bd75e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1f7bd75e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1f7bd75e

Branch: refs/heads/branch-3.0-perf
Commit: 1f7bd75e0e8514539ca27fe53b7a39a01a11c285
Parents: 19e6518
Author: Dmytro Sen <ds...@apache.org>
Authored: Thu Nov 30 10:45:18 2017 +0200
Committer: Dmytro Sen <ds...@apache.org>
Committed: Thu Nov 30 10:45:18 2017 +0200

----------------------------------------------------------------------
 .../AmbariManagementControllerImpl.java         |  9 ----
 .../internal/HostResourceProvider.java          | 54 ++++++--------------
 .../AmbariManagementControllerTest.java         | 42 +++++----------
 .../internal/HostResourceProviderTest.java      |  6 +--
 4 files changed, 30 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7bd75e/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 3d09154..455814a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -3477,15 +3477,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
               + ", hostname=" + request.getHostname()
               + ", request=" + request);
     }
-
-    // Only allow removing master/slave components in DISABLED/UNKNOWN/INSTALL_FAILED/INIT state without stages
-    // generation.
-    // Clients may be removed without a state check.
-    if (!component.isClientComponent() &&
-            !componentHost.getState().isRemovableState()) {
-      throw new AmbariException("To remove master or slave components they must be in " +
-              "DISABLED/INIT/INSTALLED/INSTALL_FAILED/UNKNOWN state. Current=" + componentHost.getState() + ".");
-    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7bd75e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
index 2b18eb2..5c740f1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
@@ -62,7 +62,6 @@ import org.apache.ambari.server.state.DesiredConfig;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.ServiceComponentHost;
-import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.apache.ambari.server.topology.ClusterTopology;
 import org.apache.ambari.server.topology.InvalidTopologyException;
@@ -146,9 +145,6 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
 
   //todo use the same json structure for cluster host addition (cluster template and upscale)
 
-  protected static final String FORCE_DELETE_COMPONENTS = "force_delete_components";
-
-
   private static final Set<String> PK_PROPERTY_IDS = ImmutableSet.of(HOST_HOST_NAME_PROPERTY_ID);
 
   @Inject
@@ -320,8 +316,6 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
 
     final Set<HostRequest> requests = new HashSet<>();
     Map<String, String> requestInfoProperties = request.getRequestInfoProperties();
-    final boolean forceDelete = requestInfoProperties.containsKey(FORCE_DELETE_COMPONENTS) &&
-                  requestInfoProperties.get(FORCE_DELETE_COMPONENTS).equals("true");
 
     for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
       requests.add(getRequest(propertyMap));
@@ -330,7 +324,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     DeleteStatusMetaData deleteStatusMetaData = modifyResources(new Command<DeleteStatusMetaData>() {
       @Override
       public DeleteStatusMetaData invoke() throws AmbariException {
-        return deleteHosts(requests, request.isDryRunRequest(), forceDelete);
+        return deleteHosts(requests, request.isDryRunRequest());
       }
     });
 
@@ -848,7 +842,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
   }
 
   @Transactional
-  protected DeleteStatusMetaData deleteHosts(Set<HostRequest> requests, boolean dryRun, boolean forceDelete)
+  protected DeleteStatusMetaData deleteHosts(Set<HostRequest> requests, boolean dryRun)
       throws AmbariException {
 
     AmbariManagementController controller = getManagementController();
@@ -863,7 +857,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
       }
 
       try {
-        validateHostInDeleteFriendlyState(hostRequest, clusters, forceDelete);
+        validateHostInDeleteFriendlyState(hostRequest, clusters);
         okToRemove.add(hostRequest);
       } catch (Exception ex) {
         deleteStatusMetaData.addException(hostName, ex);
@@ -964,7 +958,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     clusters.publishHostsDeletion(allClustersWithHosts, hostNames);
   }
 
-  private void validateHostInDeleteFriendlyState(HostRequest hostRequest, Clusters clusters, boolean forceDelete) throws AmbariException {
+  private void validateHostInDeleteFriendlyState(HostRequest hostRequest, Clusters clusters) throws AmbariException {
     Set<String> clusterNamesForHost = new HashSet<>();
     String hostName = hostRequest.getHostname();
     if (null != hostRequest.getClusterName()) {
@@ -984,43 +978,25 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
       List<ServiceComponentHost> list = cluster.getServiceComponentHosts(hostName);
 
       if (!list.isEmpty()) {
-        List<String> componentsToRemove = new ArrayList<>();
         List<String> componentsStarted = new ArrayList<>();
         for (ServiceComponentHost sch : list) {
-          componentsToRemove.add(sch.getServiceComponentName());
-          if (sch.getState() == State.STARTED) {
+          if (!sch.canBeRemoved()) {
             componentsStarted.add(sch.getServiceComponentName());
           }
         }
 
-        if (forceDelete) {
-          // error if components are running
-          if (!componentsStarted.isEmpty()) {
-            StringBuilder reason = new StringBuilder("Cannot remove host ")
-                .append(hostName)
-                .append(" from ")
-                .append(hostRequest.getClusterName())
-                .append(
-                    ".  The following roles exist, and these components must be stopped: ");
+        // error if components are running
+        if (!componentsStarted.isEmpty()) {
+          StringBuilder reason = new StringBuilder("Cannot remove host ")
+              .append(hostName)
+              .append(" from ")
+              .append(hostRequest.getClusterName())
+              .append(
+                  ".  The following roles exist, and these components are not in the removable state: ");
 
-            reason.append(StringUtils.join(componentsToRemove, ", "));
+          reason.append(StringUtils.join(componentsStarted, ", "));
 
-            throw new AmbariException(reason.toString());
-          }
-        } else {
-//          TODO why host with all components stopped can't be deleted? This functional is implemented and only this validation stops the request.
-          if (!componentsToRemove.isEmpty()) {
-            StringBuilder reason = new StringBuilder("Cannot remove host ")
-                .append(hostName)
-                .append(" from ")
-                .append(hostRequest.getClusterName())
-                .append(
-                    ".  The following roles exist, and these components must be stopped if running, and then deleted: ");
-
-            reason.append(StringUtils.join(componentsToRemove, ", "));
-
-            throw new AmbariException(reason.toString());
-          }
+          throw new AmbariException(reason.toString());
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7bd75e/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index f8b6709..e76ecb9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -8001,7 +8001,7 @@ public class AmbariManagementControllerTest {
   }
 
   @Test
-  public void testDeleteHostComponentWithForce() throws Exception {
+  public void testDeleteHostWithComponent() throws Exception {
     String cluster1 = getUniqueName();
 
     createCluster(cluster1);
@@ -8045,51 +8045,39 @@ public class AmbariManagementControllerTest {
       cHost.handleEvent(new ServiceComponentHostOpSucceededEvent(cHost.getServiceComponentName(), cHost.getHostName(), System.currentTimeMillis()));
     }
 
-    // Case 1: Attempt delete when components still exist
+    // Case 1: Attempt delete when some components are STARTED
     Set<HostRequest> requests = new HashSet<>();
     requests.clear();
     requests.add(new HostRequest(host1, cluster1));
-    try {
-      HostResourceProviderTest.deleteHosts(controller, requests, false, false);
-      fail("Expect failure deleting hosts when components exist and have not been deleted.");
-    } catch (Exception e) {
-      LOG.info("Exception is - " + e.getMessage());
-      Assert.assertTrue(e.getMessage().contains("these components must be stopped if running, and then deleted"));
-    }
 
     Service s = cluster.getService(serviceName);
     s.getServiceComponent("DATANODE").getServiceComponentHost(host1).setState(State.STARTED);
     try {
-      HostResourceProviderTest.deleteHosts(controller, requests, false, true);
+      HostResourceProviderTest.deleteHosts(controller, requests, false);
       fail("Expect failure deleting hosts when components exist and have not been stopped.");
     } catch (Exception e) {
       LOG.info("Exception is - " + e.getMessage());
-      Assert.assertTrue(e.getMessage().contains("these components must be stopped:"));
+      Assert.assertTrue(e.getMessage().contains("these components are not in the removable state:"));
     }
 
+    // Case 2: Attempt delete dryRun = true
     DeleteStatusMetaData data = null;
-    try {
-      data = HostResourceProviderTest.deleteHosts(controller, requests, true, true);
-      Assert.assertTrue(data.getDeletedKeys().size() == 0);
-    } catch (Exception e) {
-      LOG.info("Exception is - " + e.getMessage());
-      fail("Do not expect failure deleting hosts when components exist and are stopped.");
-    }
 
     LOG.info("Test dry run of delete with all host components");
     s.getServiceComponent("DATANODE").getServiceComponentHost(host1).setState(State.INSTALLED);
     try {
-      data = HostResourceProviderTest.deleteHosts(controller, requests, true, true);
+      data = HostResourceProviderTest.deleteHosts(controller, requests, true);
       Assert.assertTrue(data.getDeletedKeys().size() == 1);
     } catch (Exception e) {
       LOG.info("Exception is - " + e.getMessage());
       fail("Do not expect failure deleting hosts when components exist and are stopped.");
     }
 
+    // Case 3: Attempt delete dryRun = false
     LOG.info("Test successful delete with all host components");
     s.getServiceComponent("DATANODE").getServiceComponentHost(host1).setState(State.INSTALLED);
     try {
-      data = HostResourceProviderTest.deleteHosts(controller, requests, false, true);
+      data = HostResourceProviderTest.deleteHosts(controller, requests, false);
       Assert.assertNotNull(data);
       Assert.assertTrue(4 == data.getDeletedKeys().size());
       Assert.assertTrue(0 == data.getExceptionForKeys().size());
@@ -8154,17 +8142,11 @@ public class AmbariManagementControllerTest {
       cHost.handleEvent(new ServiceComponentHostOpSucceededEvent(cHost.getServiceComponentName(), cHost.getHostName(), System.currentTimeMillis()));
     }
 
-    // Case 1: Attempt delete when components still exist
     Set<HostRequest> requests = new HashSet<>();
     requests.clear();
     requests.add(new HostRequest(host1, cluster1));
-    try {
-      HostResourceProviderTest.deleteHosts(controller, requests);
-      fail("Expect failure deleting hosts when components exist and have not been deleted.");
-    } catch (Exception e) {
-    }
 
-    // Case 2: Delete host that is still part of cluster, but do not specify the cluster_name in the request
+    // Case 1: Delete host that is still part of cluster, but do not specify the cluster_name in the request
     Set<ServiceComponentHostRequest> schRequests = new HashSet<>();
     // Disable HC for non-clients
     schRequests.add(new ServiceComponentHostRequest(cluster1, serviceName, componentName1, host1, "DISABLED"));
@@ -8201,7 +8183,7 @@ public class AmbariManagementControllerTest {
     List<HostRoleCommandEntity> tasks = hostRoleCommandDAO.findByHostId(firstHostId);
     assertEquals(0, tasks.size());
 
-    // Case 3: Delete host that is still part of the cluster, and specify the cluster_name in the request
+    // Case 2: Delete host that is still part of the cluster, and specify the cluster_name in the request
     requests.clear();
     requests.add(new HostRequest(host2, cluster1));
     try {
@@ -8214,7 +8196,7 @@ public class AmbariManagementControllerTest {
     Assert.assertFalse(clusters.getClustersForHost(host2).contains(cluster));
     Assert.assertNull(topologyHostInfoDAO.findByHostname(host2));
 
-    // Case 4: Attempt to delete a host that has already been deleted
+    // Case 3: Attempt to delete a host that has already been deleted
     requests.clear();
     requests.add(new HostRequest(host1, null));
     try {
@@ -8232,7 +8214,7 @@ public class AmbariManagementControllerTest {
       // expected
     }
 
-    // Case 5: Attempt to delete a host that was never added to the cluster
+    // Case 4: Attempt to delete a host that was never added to the cluster
     requests.clear();
     requests.add(new HostRequest(host3, null));
     try {

http://git-wip-us.apache.org/repos/asf/ambari/blob/1f7bd75e/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
index fd28081..5e6201b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostResourceProviderTest.java
@@ -1346,11 +1346,11 @@ public class HostResourceProviderTest extends EasyMockSupport {
 
     HostResourceProvider provider = getHostProvider(controller);
     HostResourceProvider.setTopologyManager(topologyManager);
-    provider.deleteHosts(requests, false, false);
+    provider.deleteHosts(requests, false);
   }
 
   public static DeleteStatusMetaData deleteHosts(AmbariManagementController controller,
-                                                 Set<HostRequest> requests, boolean dryRun, boolean forceDelete)
+                                                 Set<HostRequest> requests, boolean dryRun)
       throws AmbariException {
     TopologyManager topologyManager = EasyMock.createNiceMock(TopologyManager.class);
     expect(topologyManager.getRequests(Collections.emptyList())).andReturn(Collections.emptyList()).anyTimes();
@@ -1359,7 +1359,7 @@ public class HostResourceProviderTest extends EasyMockSupport {
 
     HostResourceProvider provider = getHostProvider(controller);
     HostResourceProvider.setTopologyManager(topologyManager);
-    return provider.deleteHosts(requests, dryRun, forceDelete);
+    return provider.deleteHosts(requests, dryRun);
   }
 
   public static void updateHosts(AmbariManagementController controller, Set<HostRequest> requests)


[34/50] [abbrv] ambari git commit: AMBARI-22542. Upgrade Ember and jquery version for Ambari Views (pallavkul)

Posted by ao...@apache.org.
AMBARI-22542. Upgrade Ember and jquery version for Ambari Views (pallavkul)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/77503985
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/77503985
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/77503985

Branch: refs/heads/branch-3.0-perf
Commit: 7750398508b7e4dc223379be107610b5a0e792fd
Parents: ff3eca0
Author: pallavkul <pa...@gmail.com>
Authored: Wed Nov 29 21:53:49 2017 +0530
Committer: pallavkul <pa...@gmail.com>
Committed: Wed Nov 29 21:53:49 2017 +0530

----------------------------------------------------------------------
 contrib/views/files/src/main/resources/ui/bower.json             | 4 ++--
 .../views/hive-next/src/main/resources/ui/hive-web/bower.json    | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/77503985/contrib/views/files/src/main/resources/ui/bower.json
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/bower.json b/contrib/views/files/src/main/resources/ui/bower.json
index f1472ee..dacb523 100644
--- a/contrib/views/files/src/main/resources/ui/bower.json
+++ b/contrib/views/files/src/main/resources/ui/bower.json
@@ -1,12 +1,12 @@
 {
   "name": "files-view",
   "dependencies": {
-    "ember": "2.2.0",
+    "ember": "2.2.1",
     "ember-cli-shims": "0.1.0",
     "ember-cli-test-loader": "0.2.2",
     "ember-load-initializers": "0.1.7",
     "ember-qunit-notifications": "0.1.0",
-    "jquery": "1.11.3",
+    "jquery": "2.x",
     "loader.js": "^3.5.0",
     "qunit": "~1.20.0",
     "bootstrap": "~3.3.6",

http://git-wip-us.apache.org/repos/asf/ambari/blob/77503985/contrib/views/hive-next/src/main/resources/ui/hive-web/bower.json
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/bower.json b/contrib/views/hive-next/src/main/resources/ui/hive-web/bower.json
index 62861b2..e467a59 100644
--- a/contrib/views/hive-next/src/main/resources/ui/hive-web/bower.json
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/bower.json
@@ -1,8 +1,8 @@
 {
   "name": "hive",
   "dependencies": {
-    "jquery": "1.11.3",
-    "ember": "1.10.0",
+    "jquery": "2.x",
+    "ember": "1.11.4",
     "ember-data": "1.0.0-beta.16.1",
     "ember-resolver": "~0.1.12",
     "loader.js": "stefanpenner/loader.js#3.2.0",


[47/50] [abbrv] ambari git commit: Merge branch 'trunk' into branch-3.0-perf

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/ATLAS/0.1.0.2.3/package/scripts/params.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/ATLAS/0.7.0.3.0/package/scripts/params.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/DRUID/0.10.1/package/scripts/params.py
----------------------------------------------------------------------
diff --cc ambari-server/src/main/resources/common-services/DRUID/0.10.1/package/scripts/params.py
index 8430ced,519dfbf..49f73d7
--- a/ambari-server/src/main/resources/common-services/DRUID/0.10.1/package/scripts/params.py
+++ b/ambari-server/src/main/resources/common-services/DRUID/0.10.1/package/scripts/params.py
@@@ -193,8 -193,7 +193,7 @@@ if has_metric_collector
      pass
  
  # Create current Hadoop Clients  Libs
 -stack_version_unformatted = str(config['hostLevelParams']['stack_version'])
 +stack_version_unformatted = str(config['clusterLevelParams']['stack_version'])
  io_compression_codecs = default("/configurations/core-site/io.compression.codecs", None)
- lzo_enabled = io_compression_codecs is not None and "com.hadoop.compression.lzo" in io_compression_codecs.lower()
- lzo_packages = get_lzo_packages(stack_version_unformatted)
+ lzo_enabled = should_install_lzo()
  hadoop_lib_home = stack_root + '/' + stack_version + '/hadoop/lib'

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/package/scripts/hdfs.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/package/scripts/install_params.py
----------------------------------------------------------------------
diff --cc ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/package/scripts/install_params.py
index fcf0507,dc3279f..c2bf847
--- a/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/package/scripts/install_params.py
+++ b/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/package/scripts/install_params.py
@@@ -26,8 -26,4 +26,4 @@@ else
    from resource_management.libraries.script.script import Script
  
    _config = Script.get_config()
 -  stack_version_unformatted = str(_config['hostLevelParams']['stack_version'])
 +  stack_version_unformatted = str(_config['clusterLevelParams']['stack_version'])
- 
-   # The logic for LZO also exists in OOZIE's params.py
-   io_compression_codecs = default("/configurations/core-site/io.compression.codecs", None)
-   lzo_enabled = io_compression_codecs is not None and "com.hadoop.compression.lzo" in io_compression_codecs.lower()

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HDFS/3.0.0.3.0/package/scripts/hdfs.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HDFS/3.0.0.3.0/package/scripts/install_params.py
----------------------------------------------------------------------
diff --cc ambari-server/src/main/resources/common-services/HDFS/3.0.0.3.0/package/scripts/install_params.py
index fcf0507,dc3279f..c2bf847
--- a/ambari-server/src/main/resources/common-services/HDFS/3.0.0.3.0/package/scripts/install_params.py
+++ b/ambari-server/src/main/resources/common-services/HDFS/3.0.0.3.0/package/scripts/install_params.py
@@@ -26,8 -26,4 +26,4 @@@ else
    from resource_management.libraries.script.script import Script
  
    _config = Script.get_config()
 -  stack_version_unformatted = str(_config['hostLevelParams']['stack_version'])
 +  stack_version_unformatted = str(_config['clusterLevelParams']['stack_version'])
- 
-   # The logic for LZO also exists in OOZIE's params.py
-   io_compression_codecs = default("/configurations/core-site/io.compression.codecs", None)
-   lzo_enabled = io_compression_codecs is not None and "com.hadoop.compression.lzo" in io_compression_codecs.lower()

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HDFS/3.0.0.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/hive.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HIVE/0.12.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HIVE/2.1.0.3.0/package/scripts/hive.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/HIVE/2.1.0.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/SQOOP/1.4.4.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/SQOOP/1.4.4.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/TEZ/0.4.0.2.1/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/TEZ/0.4.0.2.1/package/scripts/tez.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/TEZ/0.9.0.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/TEZ/0.9.0.3.0/package/scripts/tez.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/yarn.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/yarn.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/common-services/ZEPPELIN/0.7.0/package/scripts/master.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/custom_actions/scripts/install_packages.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/custom_actions/scripts/ru_execute_tasks.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
----------------------------------------------------------------------
diff --cc ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
index 87ca569,26c79e6..9aba60f
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
@@@ -580,9 -580,9 +580,8 @@@ public class AmbariCustomCommandExecuti
      ServiceComponentDesiredStateDAO componentDAO = injector.getInstance(ServiceComponentDesiredStateDAO.class);
      RepositoryVersionHelper repoVersionHelper = injector.getInstance(RepositoryVersionHelper.class);
  
 -    CommandRepository commandRepo = repoHelper.getCommandRepository(cluster, componentRM, host);
 -    Assert.assertEquals(2, commandRepo.getRepositories().size());
 +    CommandRepository commandRepo = ambariMetaInfo.getCommandRepository(cluster, componentRM, host);
  
-     Assert.assertEquals(0, commandRepo.getRepositories().size());
  
      RepositoryInfo ri = new RepositoryInfo();
      ri.setBaseUrl("http://foo");
@@@ -608,10 -608,10 +607,10 @@@
  
      componentEntity.setDesiredRepositoryVersion(repositoryVersion);
      componentEntity.addVersion(componentVersionEntity);
-     componentEntity = componentDAO.merge(componentEntity);
+     componentDAO.merge(componentEntity);
  
      // !!! make sure the override is set
 -    commandRepo = repoHelper.getCommandRepository(cluster, componentRM, host);
 +    commandRepo = ambariMetaInfo.getCommandRepository(cluster, componentRM, host);
  
      Assert.assertEquals(1, commandRepo.getRepositories().size());
      CommandRepository.Repository repo = commandRepo.getRepositories().iterator().next();

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
----------------------------------------------------------------------
diff --cc ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
index d62e34c,ff0f687..e7b5deb
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
@@@ -163,7 -163,7 +163,7 @@@ public class KerberosIdentityCleanerTes
    }
  
    private void uninstallComponent(String service, String component, String host) throws KerberosMissingAdminCredentialsException {
-     kerberosIdentityCleaner.componentRemoved(new ServiceComponentUninstalledEvent(CLUSTER_ID, "any", "any", service, component, host, false, false));
 -    kerberosIdentityCleaner.componentRemoved(new ServiceComponentUninstalledEvent(CLUSTER_ID, "any", "any", service, component, host, false, -1l));
++    kerberosIdentityCleaner.componentRemoved(new ServiceComponentUninstalledEvent(CLUSTER_ID, "any", "any", service, component, host, false, false, -1l));
    }
  
    private void uninstallService(String service, List<Component> components) throws KerberosMissingAdminCredentialsException {

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java
----------------------------------------------------------------------
diff --cc ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java
index 1986f64,108159c..166076d
--- a/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListenerTest.java
@@@ -515,7 -514,7 +515,7 @@@ public class HostVersionOutOfSyncListen
  
          ServiceComponentUninstalledEvent event = new ServiceComponentUninstalledEvent(
              c1.getClusterId(), clusterStackId.getStackName(), clusterStackId.getStackVersion(),
-             "HDFS", "DATANODE", sch.getHostName(), false, false);
 -            "HDFS", "DATANODE", sch.getHostName(), false, -1l);
++            "HDFS", "DATANODE", sch.getHostName(), false, false, -1l);
  
          m_eventPublisher.publish(event);
        }

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFileTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
----------------------------------------------------------------------
diff --cc ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
index 52c3f62,22e8ccc..0155dd3
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog260Test.java
@@@ -683,6 -701,14 +701,14 @@@ public class UpgradeCatalog260Test 
      expect(cluster.getConfig(eq("ranger-kms-audit"), anyString())).andReturn(newConfig).once();
      expect(cluster.addDesiredConfig("ambari-upgrade", Collections.singleton(newConfig), "Updated ranger-kms-audit during Ambari Upgrade from 2.5.2 to 2.6.0.")).andReturn(response).once();
  
+     //HIVE
+     expect(cluster.getDesiredConfigByType("hive-site")).andReturn(hsiConfig).anyTimes();
+     expect(cluster.getDesiredConfigByType("hive-interactive-site")).andReturn(hsiConfig).anyTimes();
+     expect(cluster.getConfigsByType("hive-interactive-site")).andReturn(Collections.singletonMap("version1", hsiConfig)).anyTimes();
+     expect(cluster.getServiceByConfigType("hive-interactive-site")).andReturn("HIVE").anyTimes();
+     expect(cluster.getConfig(eq("hive-interactive-site"), anyString())).andReturn(newHsiConfig).anyTimes();
 -  
++
+ 
      final Clusters clusters = injector.getInstance(Clusters.class);
      expect(clusters.getCluster(2L)).andReturn(cluster).anyTimes();
  
@@@ -781,77 -845,143 +845,143 @@@
    }
  
    @Test
+   public void testUpdateHiveConfigs() throws Exception {
+ 
+     Map<String, String> oldProperties = new HashMap<String, String>() {
+       {
+         put("hive.llap.zk.sm.keytab.file", "/etc/security/keytabs/hive.llap.zk.sm.keytab");
+         put("hive.llap.daemon.keytab.file", "/etc/security/keytabs/hive.service.keytab");
+         put("hive.llap.task.keytab.file", "/etc/security/keytabs/hive.llap.task.keytab");
+       }
+     };
+     Map<String, String> newProperties = new HashMap<String, String>() {
+       {
+         put("hive.llap.zk.sm.keytab.file", "/etc/security/keytabs/hive.service.keytab");
+         put("hive.llap.daemon.keytab.file", "/etc/security/keytabs/hive.service.keytab");
+         put("hive.llap.task.keytab.file", "/etc/security/keytabs/hive.service.keytab");
+       }
+     };
+ 
+     EasyMockSupport easyMockSupport = new EasyMockSupport();
+ 
+     Clusters clusters = easyMockSupport.createNiceMock(Clusters.class);
+     final Cluster cluster = easyMockSupport.createNiceMock(Cluster.class);
+     Config mockHsiConfigs = easyMockSupport.createNiceMock(Config.class);
+ 
+     expect(clusters.getClusters()).andReturn(new HashMap<String, Cluster>() {{
+       put("normal", cluster);
+     }}).once();
+     expect(cluster.getDesiredConfigByType("hive-interactive-site")).andReturn(mockHsiConfigs).atLeastOnce();
+     expect(mockHsiConfigs.getProperties()).andReturn(oldProperties).anyTimes();
+ 
+     Injector injector = easyMockSupport.createNiceMock(Injector.class);
+     expect(injector.getInstance(Gson.class)).andReturn(null).anyTimes();
+     expect(injector.getInstance(MaintenanceStateHelper.class)).andReturn(null).anyTimes();
+ 
+     replay(injector, clusters, mockHsiConfigs, cluster);
+ 
+     AmbariManagementControllerImpl controller = createMockBuilder(AmbariManagementControllerImpl.class)
+             .addMockedMethod("createConfiguration")
+             .addMockedMethod("getClusters", new Class[] { })
+             .addMockedMethod("createConfig")
+             .withConstructor(createNiceMock(ActionManager.class), clusters, injector)
+             .createNiceMock();
+ 
+     Injector injector2 = easyMockSupport.createNiceMock(Injector.class);
+     Capture<Map> propertiesCapture = EasyMock.newCapture();
+ 
+     expect(injector2.getInstance(AmbariManagementController.class)).andReturn(controller).anyTimes();
+     expect(controller.getClusters()).andReturn(clusters).anyTimes();
+     expect(controller.createConfig(anyObject(Cluster.class), anyObject(StackId.class), anyString(), capture(propertiesCapture), anyString(),
+             anyObject(Map.class))).andReturn(createNiceMock(Config.class)).once();
+     replay(controller, injector2);
+ 
+     // This tests the update of HSI config 'hive.llap.daemon.keytab.file'.
+     UpgradeCatalog260  upgradeCatalog260 = new UpgradeCatalog260(injector2);
+     // Set 'isYarnKerberosDescUpdated' value to true, implying kerberos descriptor was updated.
+     upgradeCatalog260.updateYarnKerberosDescUpdatedList("hive.llap.zk.sm.keytab.file");
+     upgradeCatalog260.updateYarnKerberosDescUpdatedList("hive.llap.task.keytab.file");
+ 
+     upgradeCatalog260.updateHiveConfigs();
+ 
+     easyMockSupport.verifyAll();
+ 
+     Map<String, String> updatedProperties = propertiesCapture.getValue();
+     assertTrue(Maps.difference(newProperties, updatedProperties).areEqual());
+   }
+ 
+   @Test
 -   public void testHDFSWidgetUpdate() throws Exception {
 -         final Clusters clusters = createNiceMock(Clusters.class);
 -         final Cluster cluster = createNiceMock(Cluster.class);
 -         final AmbariManagementController controller = createNiceMock(AmbariManagementController.class);
 -         final Gson gson = new Gson();
 -         final WidgetDAO widgetDAO = createNiceMock(WidgetDAO.class);
 -         final AmbariMetaInfo metaInfo = createNiceMock(AmbariMetaInfo.class);
 -         WidgetEntity widgetEntity = createNiceMock(WidgetEntity.class);
 -         StackId stackId = new StackId("HDP", "2.0.0");
 -         StackInfo stackInfo = createNiceMock(StackInfo.class);
 -         ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class);
 -         Service service  = createNiceMock(Service.class);
 -
 -           String widgetStr = "{\n" +
 -             "  \"layouts\": [\n" +
 -             "      {\n" +
 -             "      \"layout_name\": \"default_hdfs_heatmap\",\n" +
 -             "      \"display_name\": \"Standard HDFS HeatMaps\",\n" +
 -             "      \"section_name\": \"HDFS_HEATMAPS\",\n" +
 -             "      \"widgetLayoutInfo\": [\n" +
 -             "        {\n" +
 -             "          \"widget_name\": \"HDFS Bytes Read\",\n" +
 -             "          \"metrics\": [],\n" +
 -             "          \"values\": []\n" +
 -             "        }\n" +
 -             "      ]\n" +
 -             "    }\n" +
 -             "  ]\n" +
 -             "}";
 -
 -           File dataDirectory = temporaryFolder.newFolder();
 -         File file = new File(dataDirectory, "hdfs_widget.json");
 -         FileUtils.writeStringToFile(file, widgetStr);
 -
 -           final Injector mockInjector = Guice.createInjector(new AbstractModule() {
 -       @Override
 -       protected void configure() {
 -                 bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
 -                 bind(AmbariManagementController.class).toInstance(controller);
 -                 bind(Clusters.class).toInstance(clusters);
 -                 bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
 -                 bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
 -                 bind(Gson.class).toInstance(gson);
 -                 bind(WidgetDAO.class).toInstance(widgetDAO);
 -                 bind(StackManagerFactory.class).toInstance(createNiceMock(StackManagerFactory.class));
 -                 bind(AmbariMetaInfo.class).toInstance(metaInfo);
 -               }
 -     });
 -         expect(controller.getClusters()).andReturn(clusters).anyTimes();
 -         expect(clusters.getClusters()).andReturn(new HashMap<String, Cluster>() {{
 -             put("normal", cluster);
 -           }}).anyTimes();
 -         expect(cluster.getServices()).andReturn(Collections.singletonMap("HDFS", service)).anyTimes();
 -         expect(cluster.getClusterId()).andReturn(1L).anyTimes();
 -         expect(service.getDesiredStackId()).andReturn(stackId).anyTimes();
 -         expect(stackInfo.getService("HDFS")).andReturn(serviceInfo);
 -         expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes();
 -         expect(metaInfo.getStack("HDP", "2.0.0")).andReturn(stackInfo).anyTimes();
 -         expect(serviceInfo.getWidgetsDescriptorFile()).andReturn(file).anyTimes();
 -
 -           expect(widgetDAO.findByName(1L, "HDFS Bytes Read", "ambari", "HDFS_HEATMAPS"))
 -             .andReturn(Collections.singletonList(widgetEntity));
 -         expect(widgetDAO.merge(widgetEntity)).andReturn(null);
 -         expect(widgetEntity.getWidgetName()).andReturn("HDFS Bytes Read").anyTimes();
 -
 -           replay(clusters, cluster, controller, widgetDAO, metaInfo, widgetEntity, stackInfo, serviceInfo, service);
 -
 -           mockInjector.getInstance(UpgradeCatalog260.class).updateHDFSWidgetDefinition();
 -
 -           verify(clusters, cluster, controller, widgetDAO, widgetEntity, stackInfo, serviceInfo);
 -       }
 +  public void testHDFSWidgetUpdate() throws Exception {
 +    final Clusters clusters = createNiceMock(Clusters.class);
 +    final Cluster cluster = createNiceMock(Cluster.class);
 +    final AmbariManagementController controller = createNiceMock(AmbariManagementController.class);
 +    final Gson gson = new Gson();
 +    final WidgetDAO widgetDAO = createNiceMock(WidgetDAO.class);
 +    final AmbariMetaInfo metaInfo = createNiceMock(AmbariMetaInfo.class);
 +    WidgetEntity widgetEntity = createNiceMock(WidgetEntity.class);
 +    StackId stackId = new StackId("HDP", "2.0.0");
 +    StackInfo stackInfo = createNiceMock(StackInfo.class);
 +    ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class);
 +    Service service  = createNiceMock(Service.class);
 +
 +    String widgetStr = "{\n" +
 +        "  \"layouts\": [\n" +
 +        "      {\n" +
 +        "      \"layout_name\": \"default_hdfs_heatmap\",\n" +
 +        "      \"display_name\": \"Standard HDFS HeatMaps\",\n" +
 +        "      \"section_name\": \"HDFS_HEATMAPS\",\n" +
 +        "      \"widgetLayoutInfo\": [\n" +
 +        "        {\n" +
 +        "          \"widget_name\": \"HDFS Bytes Read\",\n" +
 +        "          \"metrics\": [],\n" +
 +        "          \"values\": []\n" +
 +        "        }\n" +
 +        "      ]\n" +
 +        "    }\n" +
 +        "  ]\n" +
 +        "}";
 +
 +    File dataDirectory = temporaryFolder.newFolder();
 +    File file = new File(dataDirectory, "hdfs_widget.json");
 +    FileUtils.writeStringToFile(file, widgetStr);
 +
 +    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
 +      @Override
 +      protected void configure() {
 +        bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
 +        bind(AmbariManagementController.class).toInstance(controller);
 +        bind(Clusters.class).toInstance(clusters);
 +        bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
 +        bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
 +        bind(Gson.class).toInstance(gson);
 +        bind(WidgetDAO.class).toInstance(widgetDAO);
 +        bind(StackManagerFactory.class).toInstance(createNiceMock(StackManagerFactory.class));
 +        bind(AmbariMetaInfo.class).toInstance(metaInfo);
 +      }
 +    });
 +    expect(controller.getClusters()).andReturn(clusters).anyTimes();
 +    expect(clusters.getClusters()).andReturn(new HashMap<String, Cluster>() {{
 +      put("normal", cluster);
 +    }}).anyTimes();
 +    expect(cluster.getServices()).andReturn(Collections.singletonMap("HDFS", service)).anyTimes();
 +    expect(cluster.getClusterId()).andReturn(1L).anyTimes();
 +    expect(service.getDesiredStackId()).andReturn(stackId).anyTimes();
 +    expect(stackInfo.getService("HDFS")).andReturn(serviceInfo);
 +    expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes();
 +    expect(metaInfo.getStack("HDP", "2.0.0")).andReturn(stackInfo).anyTimes();
 +    expect(serviceInfo.getWidgetsDescriptorFile()).andReturn(file).anyTimes();
 +
 +    expect(widgetDAO.findByName(1L, "HDFS Bytes Read", "ambari", "HDFS_HEATMAPS"))
 +        .andReturn(Collections.singletonList(widgetEntity));
 +    expect(widgetDAO.merge(widgetEntity)).andReturn(null);
 +    expect(widgetEntity.getWidgetName()).andReturn("HDFS Bytes Read").anyTimes();
 +
 +    replay(clusters, cluster, controller, widgetDAO, metaInfo, widgetEntity, stackInfo, serviceInfo, service);
 +
 +    mockInjector.getInstance(UpgradeCatalog260.class).updateHDFSWidgetDefinition();
 +
 +    verify(clusters, cluster, controller, widgetDAO, widgetEntity, stackInfo, serviceInfo);
 +  }
  
    private Injector getInjector() {
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
----------------------------------------------------------------------
diff --cc ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
index fc59e65,747f99b..36c753e
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
@@@ -130,15 -141,15 +141,17 @@@ public class UpgradeCatalog300Test 
      Method showHcatDeletedUserMessage = UpgradeCatalog300.class.getDeclaredMethod("showHcatDeletedUserMessage");
      Method setStatusOfStagesAndRequests = UpgradeCatalog300.class.getDeclaredMethod("setStatusOfStagesAndRequests");
      Method updateLogSearchConfigs = UpgradeCatalog300.class.getDeclaredMethod("updateLogSearchConfigs");
+     Method updateKerberosConfigurations = UpgradeCatalog300.class.getDeclaredMethod("updateKerberosConfigurations");
 +    Method updateHostComponentLastStateTable = UpgradeCatalog300.class.getDeclaredMethod("updateHostComponentLastStateTable");
  
-    UpgradeCatalog300 upgradeCatalog300 = createMockBuilder(UpgradeCatalog300.class)
-             .addMockedMethod(showHcatDeletedUserMessage)
-             .addMockedMethod(addNewConfigurationsFromXml)
-             .addMockedMethod(setStatusOfStagesAndRequests)
-             .addMockedMethod(updateLogSearchConfigs)
-             .addMockedMethod(updateHostComponentLastStateTable)
-             .createMock();
+     UpgradeCatalog300 upgradeCatalog300 = createMockBuilder(UpgradeCatalog300.class)
+         .addMockedMethod(showHcatDeletedUserMessage)
+         .addMockedMethod(addNewConfigurationsFromXml)
+         .addMockedMethod(setStatusOfStagesAndRequests)
+         .addMockedMethod(updateLogSearchConfigs)
+         .addMockedMethod(updateKerberosConfigurations)
++        .addMockedMethod(updateHostComponentLastStateTable)
+         .createMock();
  
  
      upgradeCatalog300.addNewConfigurationsFromXml();
@@@ -146,9 -157,11 +159,12 @@@
      upgradeCatalog300.setStatusOfStagesAndRequests();
  
      upgradeCatalog300.updateLogSearchConfigs();
 +    upgradeCatalog300.updateHostComponentLastStateTable();
      expectLastCall().once();
  
+     upgradeCatalog300.updateKerberosConfigurations();
+     expectLastCall().once();
+ 
      replay(upgradeCatalog300);
  
      upgradeCatalog300.executeDMLUpdates();
@@@ -171,12 -184,21 +187,24 @@@
      Capture<DBAccessor.DBColumnInfo> hrcOpsDisplayNameColumn = newCapture();
      dbAccessor.addColumn(eq(UpgradeCatalog300.HOST_ROLE_COMMAND_TABLE), capture(hrcOpsDisplayNameColumn));
  
 +    Capture<DBAccessor.DBColumnInfo> lastValidColumn = newCapture();
 +    dbAccessor.addColumn(eq(UpgradeCatalog300.COMPONENT_LAST_STATE_COLUMN), capture(lastValidColumn));
 +
-     dbAccessor.dropColumn(COMPONENT_DESIRED_STATE_TABLE, SECURITY_STATE_COLUMN); expectLastCall().once();
-     dbAccessor.dropColumn(COMPONENT_STATE_TABLE, SECURITY_STATE_COLUMN); expectLastCall().once();
-     dbAccessor.dropColumn(SERVICE_DESIRED_STATE_TABLE, SECURITY_STATE_COLUMN); expectLastCall().once();
+     dbAccessor.dropColumn(COMPONENT_DESIRED_STATE_TABLE, SECURITY_STATE_COLUMN);
+     expectLastCall().once();
+     dbAccessor.dropColumn(COMPONENT_STATE_TABLE, SECURITY_STATE_COLUMN);
+     expectLastCall().once();
+     dbAccessor.dropColumn(SERVICE_DESIRED_STATE_TABLE, SECURITY_STATE_COLUMN);
+     expectLastCall().once();
+ 
+     // Ambari configuration table addition...
+     Capture<List<DBAccessor.DBColumnInfo>> ambariConfigurationTableColumns = newCapture();
+ 
+     dbAccessor.createTable(eq(AMBARI_CONFIGURATION_TABLE), capture(ambariConfigurationTableColumns));
+     expectLastCall().once();
+     dbAccessor.addPKConstraint(AMBARI_CONFIGURATION_TABLE, "PK_ambari_configuration", AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN, AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN);
+     expectLastCall().once();
+     // Ambari configuration table addition...
  
      replay(dbAccessor, configuration);
  
@@@ -189,11 -211,35 +217,40 @@@
      Assert.assertEquals(null, capturedOpsDisplayNameColumn.getDefaultValue());
      Assert.assertEquals(String.class, capturedOpsDisplayNameColumn.getType());
  
+     // Ambari configuration table addition...
+     Assert.assertTrue(ambariConfigurationTableColumns.hasCaptured());
+     List<DBAccessor.DBColumnInfo> columns = ambariConfigurationTableColumns.getValue();
+     Assert.assertEquals(3, columns.size());
+ 
+     for (DBAccessor.DBColumnInfo column : columns) {
+       String columnName = column.getName();
+ 
+       if (AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN.equals(columnName)) {
+         Assert.assertEquals(String.class, column.getType());
+         Assert.assertEquals(Integer.valueOf(100), column.getLength());
+         Assert.assertEquals(null, column.getDefaultValue());
+         Assert.assertFalse(column.isNullable());
+       } else if (AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN.equals(columnName)) {
+         Assert.assertEquals(String.class, column.getType());
+         Assert.assertEquals(Integer.valueOf(100), column.getLength());
+         Assert.assertEquals(null, column.getDefaultValue());
+         Assert.assertFalse(column.isNullable());
+       } else if (AMBARI_CONFIGURATION_PROPERTY_VALUE_COLUMN.equals(columnName)) {
+         Assert.assertEquals(String.class, column.getType());
+         Assert.assertEquals(Integer.valueOf(255), column.getLength());
+         Assert.assertEquals(null, column.getDefaultValue());
+         Assert.assertTrue(column.isNullable());
+       } else {
+         Assert.fail("Unexpected column name: " + columnName);
+       }
+     }
+     // Ambari configuration table addition...
+ 
 +    DBAccessor.DBColumnInfo capturedLastValidColumn = lastValidColumn.getValue();
 +    Assert.assertEquals(UpgradeCatalog300.HRC_OPS_DISPLAY_NAME_COLUMN, capturedLastValidColumn.getName());
 +    Assert.assertEquals(null, capturedLastValidColumn.getDefaultValue());
 +    Assert.assertEquals(String.class, capturedLastValidColumn.getType());
 +
      verify(dbAccessor);
    }
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
----------------------------------------------------------------------
diff --cc ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
index 0c855fc,17d5e77..1d822eb
--- a/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
+++ b/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
@@@ -164,9 -164,9 +164,9 @@@ class TestRUExecuteTasks(RMFTestCase)
      call_mock.side_effect = fake_call   # echo the command
  
      # Ensure that the json file was actually read.
 -    stack_name = default("/hostLevelParams/stack_name", None)
 +    stack_name = default("/clusterLevelParams/stack_name", None)
      stack_version = default("/hostLevelParams/stack_version", None)
-     service_package_folder = default('/roleParams/service_package_folder', None)
+     service_package_folder = default('/commandParams/service_package_folder', None)
  
      self.assertEqual(stack_name, "HDP")
      self.assertEqual(stack_version, '2.2')

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/python/stacks/2.0.6/HIVE/test_hive_server.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/test/python/stacks/2.6/common/test_stack_advisor.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/controllers/global/update_controller.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/controllers/main/dashboard/config_history_controller.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/mappers/components_state_mapper.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --cc ambari-web/app/messages.js
index 4a352ed,b294877..fe6f3ac
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@@ -358,8 -358,8 +358,9 @@@ Em.I18n.translations = 
    'common.repositoryType': 'Repository Type',
    'common.rolling.downgrade': 'Rolling Downgrade',
    'common.express.downgrade': 'Express Downgrade',
 +  'common.minute.ago': 'less than a minute ago',
    'common.views': 'Views',
+   'common.critical.error': 'Critical',
  
    'models.alert_instance.tiggered.verbose': "Occurred on {0} <br> Checked on {1}",
    'models.alert_definition.triggered.verbose': "Occurred on {0}",

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/app/views/main/dashboard/config_history_view.js
----------------------------------------------------------------------
diff --cc ambari-web/app/views/main/dashboard/config_history_view.js
index ae479dd,4376067..aa2bbb6
--- a/ambari-web/app/views/main/dashboard/config_history_view.js
+++ b/ambari-web/app/views/main/dashboard/config_history_view.js
@@@ -67,15 -68,10 +67,9 @@@ App.MainConfigHistoryView = App.TableVi
     * stop polling after leaving config history page
     */
    willDestroyElement: function () {
 -    this.set('controller.isPolling', false);
 -    clearTimeout(this.get('controller.timeoutRef'));
 +    this.get('controller').unsubscribeOfUpdates();
    },
  
-   updateFilter: function (iColumn, value, type) {
-     if (!this.get('isInitialRendering')) {
-       this._super(iColumn, value, type);
-     }
-   },
- 
    sortView: sort.serverWrapperView,
    versionSort: sort.fieldView.extend({
      column: 1,

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-web/test/views/main/dashboard/config_history_view_test.js
----------------------------------------------------------------------
diff --cc ambari-web/test/views/main/dashboard/config_history_view_test.js
index 090868e,a104e25..070c532
--- a/ambari-web/test/views/main/dashboard/config_history_view_test.js
+++ b/ambari-web/test/views/main/dashboard/config_history_view_test.js
@@@ -286,46 -135,10 +131,17 @@@ describe('App.MainConfigHistoryView', f
      });
    });
  
-   describe('#updateFilter()', function () {
-     var cases = [
-       {
-         isInitialRendering: false,
-         updateFilterCalled: true,
-         title: 'updateFilter should be called'
-       },
-       {
-         isInitialRendering: true,
-         updateFilterCalled: false,
-         title: 'updateFilter should not be called'
-       }
-     ];
-     beforeEach(function () {
-       sinon.stub(view, 'saveFilterConditions', Em.K);
-       view.set('filteringComplete', true);
-     });
-     afterEach(function () {
-       view.saveFilterConditions.restore();
-     });
-     cases.forEach(function (item) {
-       it(item.title, function () {
-         view.set('isInitialRendering', item.isInitialRendering);
-         view.updateFilter(1, 'value', 'string');
-         expect(view.get('saveFilterConditions').calledWith(1, 'value', 'string')).to.equal(item.updateFilterCalled);
-       });
-     });
-   });
- 
    describe('#willDestroyElement()', function() {
 -    it('controller.isPolling is false', function() {
 +    beforeEach(function () {
 +      sinon.stub(view.get('controller'), 'unsubscribeOfUpdates');
 +    });
 +    afterEach(function () {
 +      view.get('controller').unsubscribeOfUpdates.restore();
 +    });
 +
 +    it('unsubscribeOfUpdates should be called', function() {
        view.willDestroyElement();
 -      expect(view.get('controller.isPolling')).to.be.false;
 +      expect(view.get('controller').unsubscribeOfUpdates.calledOnce).to.be.true;
      });
    });
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/pom.xml
----------------------------------------------------------------------


[18/50] [abbrv] ambari git commit: AMBARI-22520. PERF stack: deploy fails due to incorrect stack upgrade related information (aonishuk)

Posted by ao...@apache.org.
AMBARI-22520. PERF stack: deploy fails due to incorrect stack upgrade related information (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b832f706
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b832f706
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b832f706

Branch: refs/heads/branch-3.0-perf
Commit: b832f70620f9f018421479efbf056d8e4c014339
Parents: 0b98ccd
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Tue Nov 28 12:16:04 2017 +0200
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Tue Nov 28 12:16:04 2017 +0200

----------------------------------------------------------------------
 .../PERF/1.0/configuration/cluster-env.xml      | 26 ++++++++++++++++++++
 .../PERF/1.0/properties/stack_packages.json     |  8 ++++++
 2 files changed, 34 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b832f706/ambari-server/src/main/resources/stacks/PERF/1.0/configuration/cluster-env.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/PERF/1.0/configuration/cluster-env.xml b/ambari-server/src/main/resources/stacks/PERF/1.0/configuration/cluster-env.xml
index f19ac52..12a0527 100644
--- a/ambari-server/src/main/resources/stacks/PERF/1.0/configuration/cluster-env.xml
+++ b/ambari-server/src/main/resources/stacks/PERF/1.0/configuration/cluster-env.xml
@@ -109,4 +109,30 @@
     </value-attributes>
     <on-ambari-upgrade add="true"/>
   </property>
+  <!-- Define stack_packages property in the base stack. DO NOT override this property for each stack version -->
+  <property>
+    <name>stack_packages</name>
+    <value/>
+    <description>Associations between component and stack-select tools.</description>
+    <property-type>VALUE_FROM_PROPERTY_FILE</property-type>
+    <value-attributes>
+      <property-file-name>stack_packages.json</property-file-name>
+      <property-file-type>json</property-file-type>
+      <read-only>true</read-only>
+      <overridable>false</overridable>
+      <visible>false</visible>
+    </value-attributes>
+    <on-ambari-upgrade add="true"/>
+  </property>
+  <property>
+    <name>stack_root</name>
+    <value>{"PERF":"/usr/perf"}</value>
+    <description>JSON which defines the stack root by stack name</description>
+    <value-attributes>
+      <read-only>true</read-only>
+      <overridable>false</overridable>
+      <visible>false</visible>
+    </value-attributes>
+    <on-ambari-upgrade add="true"/>
+  </property>
 </configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b832f706/ambari-server/src/main/resources/stacks/PERF/1.0/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/PERF/1.0/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/PERF/1.0/properties/stack_packages.json
new file mode 100644
index 0000000..6930fe6
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/PERF/1.0/properties/stack_packages.json
@@ -0,0 +1,8 @@
+{
+  "PERF": {
+    "stack-select": {
+    },
+    "upgrade-dependencies" : {
+    }
+  }
+}


[16/50] [abbrv] ambari git commit: AMBARI-22521. Log Search: Adding new dynamic field for service logs (oleewere)

Posted by ao...@apache.org.
AMBARI-22521. Log Search: Adding new dynamic field for service logs (oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/74bc7401
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/74bc7401
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/74bc7401

Branch: refs/heads/branch-3.0-perf
Commit: 74bc7401cdeeec5fed8f0ba28f68d4e05d83af62
Parents: 1d9985c
Author: Oliver Szabo <ol...@gmail.com>
Authored: Mon Nov 27 17:40:04 2017 +0100
Committer: Oliver Szabo <ol...@gmail.com>
Committed: Mon Nov 27 18:06:16 2017 +0100

----------------------------------------------------------------------
 .../configsets/hadoop_logs/conf/managed-schema     |  2 ++
 .../ambari/logsearch/solr/SolrConstants.java       |  1 +
 .../logsearch/solr/model/SolrServiceLogData.java   | 17 +++++++++++++++++
 3 files changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/74bc7401/ambari-logsearch/ambari-logsearch-server/src/main/configsets/hadoop_logs/conf/managed-schema
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-server/src/main/configsets/hadoop_logs/conf/managed-schema b/ambari-logsearch/ambari-logsearch-server/src/main/configsets/hadoop_logs/conf/managed-schema
index c6f498b..93b2d6b 100644
--- a/ambari-logsearch/ambari-logsearch-server/src/main/configsets/hadoop_logs/conf/managed-schema
+++ b/ambari-logsearch/ambari-logsearch-server/src/main/configsets/hadoop_logs/conf/managed-schema
@@ -115,6 +115,8 @@
   <dynamicField name='std_*' type="text_std_token_lower_case" multiValued="false" stored="false"/>
   <dynamicField name='key_*' type="key_lower_case" multiValued="false" stored="false"/>
   <dynamicField name="ws_*" type="text_ws" multiValued="false" omitNorms="false" stored="false"/>
+  <dynamicField name="sdi_*" type="text_ws" omitNorms="false" multiValued="false" stored="true"/>
+
   <copyField source="log_message" dest="key_log_message"/>
 
 </schema>

http://git-wip-us.apache.org/repos/asf/ambari/blob/74bc7401/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/SolrConstants.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/SolrConstants.java b/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/SolrConstants.java
index 60fc1a3..6554bcf 100644
--- a/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/SolrConstants.java
+++ b/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/SolrConstants.java
@@ -66,6 +66,7 @@ public class SolrConstants {
     public static final String STORED_TOKEN_DYNAMIC_FIELDS = "std_*";
     public static final String KEY_DYNAMIC_FIELDS = "key_*";
     public static final String WS_DYNAMIC_FIELDS = "ws_*";
+    public static final String SDI_DYNAMIC_FIELDS = "sdi_*";
   }
 
   public class AuditLogConstants {

http://git-wip-us.apache.org/repos/asf/ambari/blob/74bc7401/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/model/SolrServiceLogData.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/model/SolrServiceLogData.java b/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/model/SolrServiceLogData.java
index c6fdba3..224ed8c 100644
--- a/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/model/SolrServiceLogData.java
+++ b/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/solr/model/SolrServiceLogData.java
@@ -22,6 +22,7 @@ import org.apache.ambari.logsearch.model.response.ServiceLogData;
 import org.apache.solr.client.solrj.beans.Field;
 
 import java.util.Date;
+import java.util.Map;
 
 import static org.apache.ambari.logsearch.solr.SolrConstants.ServiceLogConstants.*;
 
@@ -48,6 +49,9 @@ public class SolrServiceLogData extends SolrCommonLogData implements ServiceLogD
   @Field(HOST)
   private String host;
 
+  @Field(SDI_DYNAMIC_FIELDS)
+  private Map<String, Object> sdiDynamicFields;
+
   @Override
   public String getPath() {
     return path;
@@ -117,4 +121,17 @@ public class SolrServiceLogData extends SolrCommonLogData implements ServiceLogD
   public void setLevel(String level) {
     this.level = level;
   }
+
+  public void setSdiDynamicFields(Map<String, Object> sdiDynamicFields) {
+    this.sdiDynamicFields = sdiDynamicFields;
+  }
+
+  @Override
+  public Map<String, Object> getAllDynamicFields() {
+    Map<String, Object> dynamicFieldsMap = super.getAllDynamicFields();
+    if (sdiDynamicFields != null) {
+      dynamicFieldsMap.putAll(sdiDynamicFields);
+    }
+    return dynamicFieldsMap;
+  }
 }


[33/50] [abbrv] ambari git commit: AMBARI-22545 - Tie MapReduce to Hive and Tez For Patch Upgrades (jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22545 - Tie MapReduce to Hive and Tez For Patch Upgrades (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ff3eca0e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ff3eca0e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ff3eca0e

Branch: refs/heads/branch-3.0-perf
Commit: ff3eca0ef9f33c45c162669a94a61a6a172ece3a
Parents: 0cf8276
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Wed Nov 29 09:47:46 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Wed Nov 29 10:59:02 2017 -0500

----------------------------------------------------------------------
 .../resources/stacks/HDP/2.0.6/properties/stack_packages.json    | 4 +++-
 .../main/resources/stacks/HDP/3.0/properties/stack_packages.json | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ff3eca0e/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
index 794d2b0..1783655 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/properties/stack_packages.json
@@ -1277,7 +1277,9 @@
       }
     },
     "upgrade-dependencies" : {
-      "HIVE": ["TEZ"],
+      "HIVE": ["TEZ", "MAPREDUCE2"],
+      "TEZ": ["HIVE"],
+      "MAPREDUCE2": ["HIVE"],
       "MAHOUT": ["MAPREDUCE2"],
       "OOZIE": ["MAPREDUCE2"]
     }    

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff3eca0e/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json b/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
index 5fb61c8..4b4d0bb 100644
--- a/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
+++ b/ambari-server/src/main/resources/stacks/HDP/3.0/properties/stack_packages.json
@@ -1154,7 +1154,9 @@
       }
     },
     "upgrade-dependencies" : {
-      "HIVE": ["TEZ"],
+      "HIVE": ["TEZ", "MAPREDUCE2"],
+      "TEZ": ["HIVE"],
+      "MAPREDUCE2": ["HIVE"],
       "MAHOUT": ["MAPREDUCE2"],
       "OOZIE": ["MAPREDUCE2"]
     }    


[17/50] [abbrv] ambari git commit: AMBARI-22524 : Journal Node start failing when AMS is installed during BP deploy. (avijayan)

Posted by ao...@apache.org.
AMBARI-22524 : Journal Node start failing when AMS is installed during BP deploy. (avijayan)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0b98ccd7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0b98ccd7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0b98ccd7

Branch: refs/heads/branch-3.0-perf
Commit: 0b98ccd75c54c147638c7380d59a067afbea8145
Parents: 74bc740
Author: Aravindan Vijayan <av...@hortonworks.com>
Authored: Mon Nov 27 11:45:40 2017 -0800
Committer: Aravindan Vijayan <av...@hortonworks.com>
Committed: Mon Nov 27 11:45:40 2017 -0800

----------------------------------------------------------------------
 .../ambari-metrics-hadoop-sink/pom.xml          |  3 ++-
 .../timeline/HadoopTimelineMetricsSink.java     |  6 +++---
 .../timeline/HadoopTimelineMetricsSinkTest.java | 21 ++++++++++----------
 3 files changed, 16 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/0b98ccd7/ambari-metrics/ambari-metrics-hadoop-sink/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-hadoop-sink/pom.xml b/ambari-metrics/ambari-metrics-hadoop-sink/pom.xml
index 23f9ba9..a9d342f 100644
--- a/ambari-metrics/ambari-metrics-hadoop-sink/pom.xml
+++ b/ambari-metrics/ambari-metrics-hadoop-sink/pom.xml
@@ -31,6 +31,7 @@ limitations under the License.
   <packaging>jar</packaging>
   <properties>
     <sinkJarName>${project.artifactId}-with-common-${project.version}.jar</sinkJarName>
+    <hadoop.version>3.0.0-beta1</hadoop.version>
   </properties>
 
 
@@ -141,7 +142,7 @@ limitations under the License.
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-common</artifactId>
-      <version>2.4.0</version>
+      <version>${hadoop.version}</version>
       <scope>compile</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/0b98ccd7/ambari-metrics/ambari-metrics-hadoop-sink/src/main/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSink.java
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-hadoop-sink/src/main/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSink.java b/ambari-metrics/ambari-metrics-hadoop-sink/src/main/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSink.java
index a290ced..bbc9617 100644
--- a/ambari-metrics/ambari-metrics-hadoop-sink/src/main/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSink.java
+++ b/ambari-metrics/ambari-metrics-hadoop-sink/src/main/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSink.java
@@ -17,7 +17,8 @@
  */
 package org.apache.hadoop.metrics2.sink.timeline;
 
-import org.apache.commons.configuration.SubsetConfiguration;
+import org.apache.commons.configuration2.SubsetConfiguration;
+import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
 import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
@@ -34,7 +35,6 @@ import java.io.IOException;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -143,7 +143,7 @@ public class HadoopTimelineMetricsSink extends AbstractTimelineMetricsSink imple
     metricsCache = new TimelineMetricsCache(maxRowCacheSize,
       metricsSendInterval, conf.getBoolean(SKIP_COUNTER_TRANSFROMATION, true));
 
-    conf.setListDelimiter(',');
+    conf.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
     Iterator<String> it = (Iterator<String>) conf.getKeys();
     while (it.hasNext()) {
       String propertyName = it.next();

http://git-wip-us.apache.org/repos/asf/ambari/blob/0b98ccd7/ambari-metrics/ambari-metrics-hadoop-sink/src/test/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSinkTest.java
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-hadoop-sink/src/test/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSinkTest.java b/ambari-metrics/ambari-metrics-hadoop-sink/src/test/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSinkTest.java
index 30c5c23..6bb6454 100644
--- a/ambari-metrics/ambari-metrics-hadoop-sink/src/test/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSinkTest.java
+++ b/ambari-metrics/ambari-metrics-hadoop-sink/src/test/java/org/apache/hadoop/metrics2/sink/timeline/HadoopTimelineMetricsSinkTest.java
@@ -19,7 +19,8 @@
 package org.apache.hadoop.metrics2.sink.timeline;
 
 import com.google.gson.Gson;
-import org.apache.commons.configuration.SubsetConfiguration;
+import org.apache.commons.configuration2.SubsetConfiguration;
+import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
 import org.apache.commons.io.IOUtils;
 import org.apache.hadoop.metrics2.AbstractMetric;
 import org.apache.hadoop.metrics2.MetricType;
@@ -74,7 +75,7 @@ import static org.powermock.api.easymock.PowerMock.replayAll;
 import static org.powermock.api.easymock.PowerMock.verifyAll;
 
 @RunWith(PowerMockRunner.class)
-@PrepareForTest({AbstractTimelineMetricsSink.class, HttpURLConnection.class})
+@PrepareForTest({AbstractTimelineMetricsSink.class, HttpURLConnection.class, SubsetConfiguration.class})
 public class HadoopTimelineMetricsSinkTest {
   Gson gson = new Gson();
 
@@ -84,7 +85,7 @@ public class HadoopTimelineMetricsSinkTest {
   }
 
   @Test
-  @PrepareForTest({URL.class, OutputStream.class, AbstractTimelineMetricsSink.class, HttpURLConnection.class, TimelineMetric.class, HadoopTimelineMetricsSink.class})
+  @PrepareForTest({URL.class, OutputStream.class, AbstractTimelineMetricsSink.class, HttpURLConnection.class, TimelineMetric.class, HadoopTimelineMetricsSink.class, SubsetConfiguration.class})
   public void testPutMetrics() throws Exception {
     HadoopTimelineMetricsSink sink = new HadoopTimelineMetricsSink();
 
@@ -102,7 +103,7 @@ public class HadoopTimelineMetricsSinkTest {
     OutputStream os = PowerMock.createNiceMock(OutputStream.class);
     expect(connection.getOutputStream()).andReturn(os).anyTimes();
 
-    SubsetConfiguration conf = createNiceMock(SubsetConfiguration.class);
+    SubsetConfiguration conf = PowerMock.createNiceMock(SubsetConfiguration.class);
     expect(conf.getString("slave.host.name")).andReturn("localhost").anyTimes();
     expect(conf.getParent()).andReturn(null).anyTimes();
     expect(conf.getPrefix()).andReturn("service").anyTimes();
@@ -116,7 +117,7 @@ public class HadoopTimelineMetricsSinkTest {
     expect(conf.getBoolean(eq(SET_INSTANCE_ID_PROPERTY), eq(false))).andReturn(true).anyTimes();
     expect(conf.getString(eq(INSTANCE_ID_PROPERTY), anyString())).andReturn("instanceId").anyTimes();
 
-    conf.setListDelimiter(eq(','));
+    conf.setListDelimiterHandler(new DefaultListDelimiterHandler(eq(',')));
     expectLastCall().anyTimes();
 
     expect(conf.getKeys()).andReturn(new Iterator() {
@@ -157,7 +158,7 @@ public class HadoopTimelineMetricsSinkTest {
     timelineMetric.setInstanceId(eq("instanceId"));
     EasyMock.expectLastCall();
 
-    replay(conf, record, metric);
+    replay(record, metric);
     replayAll();
 
     sink.init(conf);
@@ -179,7 +180,7 @@ public class HadoopTimelineMetricsSinkTest {
         .addMockedMethod("findLiveCollectorHostsFromKnownCollector")
         .addMockedMethod("emitMetrics").createNiceMock();
 
-    SubsetConfiguration conf = createNiceMock(SubsetConfiguration.class);
+    SubsetConfiguration conf = PowerMock.createNiceMock(SubsetConfiguration.class);
     expect(conf.getString("slave.host.name")).andReturn("localhost").anyTimes();
     expect(conf.getParent()).andReturn(null).anyTimes();
     expect(conf.getPrefix()).andReturn("service").anyTimes();
@@ -198,7 +199,7 @@ public class HadoopTimelineMetricsSinkTest {
     expect(sink.findLiveCollectorHostsFromKnownCollector("localhost2", "6188"))
             .andReturn(Collections.singletonList("localhost2")).anyTimes();
 
-    conf.setListDelimiter(eq(','));
+    conf.setListDelimiterHandler(new DefaultListDelimiterHandler(eq(',')));
     expectLastCall().anyTimes();
 
     expect(conf.getKeys()).andReturn(new Iterator() {
@@ -309,7 +310,7 @@ public class HadoopTimelineMetricsSinkTest {
         .addMockedMethod("findLiveCollectorHostsFromKnownCollector")
         .addMockedMethod("emitMetrics").createNiceMock();
 
-    SubsetConfiguration conf = createNiceMock(SubsetConfiguration.class);
+    SubsetConfiguration conf = PowerMock.createNiceMock(SubsetConfiguration.class);
     expect(conf.getString("slave.host.name")).andReturn("localhost").anyTimes();
     expect(conf.getParent()).andReturn(null).anyTimes();
     expect(conf.getPrefix()).andReturn("service").anyTimes();
@@ -326,7 +327,7 @@ public class HadoopTimelineMetricsSinkTest {
     expect(conf.getInt(eq(MAX_METRIC_ROW_CACHE_SIZE), anyInt())).andReturn(10).anyTimes();
     expect(conf.getInt(eq(METRICS_SEND_INTERVAL), anyInt())).andReturn(10).anyTimes();
 
-    conf.setListDelimiter(eq(','));
+    conf.setListDelimiterHandler(new DefaultListDelimiterHandler(eq(',')));
     expectLastCall().anyTimes();
 
     Set<String> rpcPortSuffixes = new HashSet<String>() {{


[20/50] [abbrv] ambari git commit: AMBARI-22526. Log Feeder: handle multiple '=' (split char) in key/value filter (oleewere)

Posted by ao...@apache.org.
AMBARI-22526. Log Feeder: handle multiple '=' (split char) in key/value filter (oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/33ee1a73
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/33ee1a73
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/33ee1a73

Branch: refs/heads/branch-3.0-perf
Commit: 33ee1a7381237a6cd4a5159d0f8ddc601f342529
Parents: 530f1d5
Author: Oliver Szabo <ol...@gmail.com>
Authored: Tue Nov 28 15:08:51 2017 +0100
Committer: Oliver Szabo <ol...@gmail.com>
Committed: Tue Nov 28 15:17:31 2017 +0100

----------------------------------------------------------------------
 .../java/org/apache/ambari/logfeeder/filter/FilterKeyValue.java  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/33ee1a73/ambari-logsearch/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/filter/FilterKeyValue.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/filter/FilterKeyValue.java b/ambari-logsearch/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/filter/FilterKeyValue.java
index 670b1c3..8e5aee8 100644
--- a/ambari-logsearch/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/filter/FilterKeyValue.java
+++ b/ambari-logsearch/ambari-logsearch-logfeeder/src/main/java/org/apache/ambari/logfeeder/filter/FilterKeyValue.java
@@ -128,14 +128,14 @@ public class FilterKeyValue extends Filter {
 
   private String[] getNameValue(String nv) {
     String splitPattern = Pattern.quote(valueSplit);
-    return nv.split(splitPattern);
+    return nv.split(splitPattern, 2);
   }
 
   private void logParseError(String inputStr) {
     errorMetric.value++;
     String logMessageKey = this.getClass().getSimpleName() + "_PARSEERROR";
     LogFeederUtil.logErrorMessageByInterval(logMessageKey, "Error parsing string. length=" + inputStr.length() + ", input=" +
-        input.getShortDescription() + ". First upto 100 characters=" + StringUtils.abbreviate(inputStr, 100), null, LOG,
+        input.getShortDescription() + ". First upto 200 characters=" + StringUtils.abbreviate(inputStr, 200), null, LOG,
         Level.ERROR);
   }
 


[30/50] [abbrv] ambari git commit: AMBARI-22535 - Remove extjs From Oozie Installations By Default (jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22535 - Remove extjs From Oozie Installations By Default (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/31a0f197
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/31a0f197
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/31a0f197

Branch: refs/heads/branch-3.0-perf
Commit: 31a0f1971a2be44c5322e7817a57d9e8aa1b606c
Parents: 11d7a6a
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Tue Nov 28 13:50:49 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue Nov 28 15:27:27 2017 -0500

----------------------------------------------------------------------
 .../OOZIE/4.2.0.3.0/metainfo.xml                |  9 ++---
 .../stacks/HDP/2.6/services/OOZIE/metainfo.xml  | 37 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/31a0f197/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/metainfo.xml b/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/metainfo.xml
index 47b3705..11ef853 100644
--- a/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/metainfo.xml
+++ b/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/metainfo.xml
@@ -25,7 +25,8 @@
         <enabled>true</enabled>
       </credential-store>
       <displayName>Oozie</displayName>
-      <comment>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 &lt;a target="_blank" href="http://www.sencha.com/legal/open-source-faq/"&gt;ExtJS&lt;/a&gt; Library.
+      <comment>
+        System for workflow coordination and execution of Apache Hadoop jobs.
       </comment>
       <version>4.2.0.3.0</version>
       <components>
@@ -125,9 +126,6 @@
             <package>
               <name>zip</name>
             </package>
-            <package>
-              <name>extjs</name>
-            </package>
           </packages>
         </osSpecific>
         <osSpecific>
@@ -150,9 +148,6 @@
             <package>
               <name>falcon-${stack_version}</name>
             </package>
-            <package>
-              <name>extjs</name>
-            </package>
           </packages>
         </osSpecific>
       </osSpecifics>

http://git-wip-us.apache.org/repos/asf/ambari/blob/31a0f197/ambari-server/src/main/resources/stacks/HDP/2.6/services/OOZIE/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/services/OOZIE/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/services/OOZIE/metainfo.xml
index c9dfaad..9b12d01 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/services/OOZIE/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/services/OOZIE/metainfo.xml
@@ -20,7 +20,44 @@
   <services>
     <service>
       <name>OOZIE</name>
+      <comment>
+        System for workflow coordination and execution of Apache Hadoop jobs.
+      </comment>      
       <version>4.2.0</version>
+
+      <osSpecifics>
+        <osSpecific>
+          <osFamily>any</osFamily>
+          <packages>
+            <package>
+              <name>zip</name>
+            </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>redhat5,amazon2015,redhat6,redhat7,suse11,suse12</osFamily>
+          <packages>
+            <package>
+              <name>oozie_${stack_version}</name>
+            </package>
+            <package>
+              <name>falcon_${stack_version}</name>
+            </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>debian7,ubuntu12,ubuntu14,ubuntu16</osFamily>
+          <packages>
+            <package>
+              <name>oozie-${stack_version}</name>
+            </package>
+            <package>
+              <name>falcon-${stack_version}</name>
+            </package>
+          </packages>
+        </osSpecific>
+      </osSpecifics>
+
       <configuration-dependencies>
         <config-type>application-properties</config-type>
       </configuration-dependencies>


[26/50] [abbrv] ambari git commit: AMBARI-22523. Service config changes on hdp + hdf cluster throws Consistency check failed. (mpapirkovskyy)

Posted by ao...@apache.org.
AMBARI-22523. Service config changes on hdp + hdf cluster throws Consistency check failed. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/020e1528
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/020e1528
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/020e1528

Branch: refs/heads/branch-3.0-perf
Commit: 020e15281e6466ae436d228dcc7428c86560882a
Parents: 73d99d8
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Mon Nov 20 17:19:12 2017 +0200
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Tue Nov 28 18:31:29 2017 +0200

----------------------------------------------------------------------
 .../resources/stacks/HDP/2.6/services/stack_advisor.py   |  3 +++
 .../test/python/stacks/2.6/common/test_stack_advisor.py  | 11 +++++++++++
 2 files changed, 14 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/020e1528/ambari-server/src/main/resources/stacks/HDP/2.6/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.6/services/stack_advisor.py
index fc12d37..6951282 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/services/stack_advisor.py
@@ -640,6 +640,9 @@ class HDP26StackAdvisor(HDP25StackAdvisor):
         else:
             druid_broker_host_port = "localhost:8083"
 
+        druid_metadata_uri = ""
+        druid_metadata_user = ""
+        druid_metadata_type = ""
         if 'druid-common' in services['configurations']:
             druid_metadata_uri = services['configurations']['druid-common']['properties']['druid.metadata.storage.connector.connectURI']
             druid_metadata_type = services['configurations']['druid-common']['properties']['druid.metadata.storage.type']

http://git-wip-us.apache.org/repos/asf/ambari/blob/020e1528/ambari-server/src/test/python/stacks/2.6/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.6/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.6/common/test_stack_advisor.py
index f4c5508..b112ffb 100644
--- a/ambari-server/src/test/python/stacks/2.6/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.6/common/test_stack_advisor.py
@@ -1949,6 +1949,17 @@ class TestHDP26StackAdvisor(TestCase):
     self.stackAdvisor.recommendHIVEConfigurations(recommendedConfigurations, clusterData, services, hosts)
     self.assertEquals(recommendedConfigurations, expected)
 
+    # case there are not druid-common configs present
+    del services['configurations']['druid-common']
+    expected['hive-interactive-site']['properties']['hive.druid.broker.address.default'] = 'c6401.ambari.apache.org:8083'
+    expected['hive-interactive-site']['properties']['hive.druid.metadata.uri'] = ''
+    expected['hive-interactive-site']['properties']['hive.druid.metadata.username'] = ''
+    expected['hive-interactive-site']['properties']['hive.druid.metadata.db.type'] = ''
+
+    recommendedConfigurations = {}
+    self.stackAdvisor.recommendHIVEConfigurations(recommendedConfigurations, clusterData, services, hosts)
+    self.assertEquals(recommendedConfigurations, expected)
+
 
   def test_recommendHBASEConfigurations(self):
     configurations = {


[12/50] [abbrv] ambari git commit: AMBARI-22402. PERF stack: Deploy fails due to common hooks being used instead of one specific to PERF (aonishuk)

Posted by ao...@apache.org.
AMBARI-22402. PERF stack: Deploy fails due to common hooks being used instead of one specific to PERF (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3dca5607
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3dca5607
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3dca5607

Branch: refs/heads/branch-3.0-perf
Commit: 3dca5607d736f5d70ef0a48898c2e009fd60b50a
Parents: c9936ad
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Mon Nov 27 15:06:24 2017 +0200
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Mon Nov 27 15:06:24 2017 +0200

----------------------------------------------------------------------
 .../ambari/server/actionmanager/ExecutionCommandWrapper.java  | 7 +++++--
 .../java/org/apache/ambari/server/agent/HeartbeatMonitor.java | 3 +--
 .../org/apache/ambari/server/configuration/Configuration.java | 7 +++++++
 .../server/controller/internal/UpgradeResourceProvider.java   | 3 +--
 .../java/org/apache/ambari/server/stack/StackManager.java     | 5 -----
 contrib/utils/perf/deploy-gce-perf-cluster.py                 | 1 +
 6 files changed, 15 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3dca5607/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
index a0c5f26..7b693cd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
@@ -20,7 +20,6 @@ package org.apache.ambari.server.actionmanager;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
-import static org.apache.ambari.server.stack.StackManager.DEFAULT_HOOKS_FOLDER;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -34,6 +33,7 @@ import org.apache.ambari.server.agent.AgentCommand.AgentCommandType;
 import org.apache.ambari.server.agent.CommandRepository;
 import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.entities.OperatingSystemEntity;
@@ -93,6 +93,9 @@ public class ExecutionCommandWrapper {
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
 
+  @Inject
+  private Configuration configuration;
+
   @AssistedInject
   public ExecutionCommandWrapper(@Assisted String jsonExecutionCommand) {
     this.jsonExecutionCommand = jsonExecutionCommand;
@@ -304,7 +307,7 @@ public class ExecutionCommandWrapper {
           stackId.getStackVersion());
 
         if (!commandParams.containsKey(HOOKS_FOLDER)) {
-          commandParams.put(HOOKS_FOLDER, DEFAULT_HOOKS_FOLDER);
+          commandParams.put(HOOKS_FOLDER,configuration.getProperty(Configuration.HOOKS_FOLDER));
         }
 
         if (!commandParams.containsKey(SERVICE_PACKAGE_FOLDER)) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/3dca5607/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
index c13df6b..d51364e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
@@ -25,7 +25,6 @@ import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TY
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
-import static org.apache.ambari.server.stack.StackManager.DEFAULT_HOOKS_FOLDER;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -341,7 +340,7 @@ public class HeartbeatMonitor implements Runnable {
     commandParams.put(COMMAND_TIMEOUT, commandTimeout);
     commandParams.put(SERVICE_PACKAGE_FOLDER,
        serviceInfo.getServicePackageFolder());
-    commandParams.put(HOOKS_FOLDER, DEFAULT_HOOKS_FOLDER);
+    commandParams.put(HOOKS_FOLDER, configuration.getProperty(Configuration.HOOKS_FOLDER));
     // Fill host level params
     Map<String, String> hostLevelParams = statusCmd.getHostLevelParams();
     hostLevelParams.put(JDK_LOCATION, ambariManagementController.getJdkResourceUrl());

http://git-wip-us.apache.org/repos/asf/ambari/blob/3dca5607/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index a53aebd..ea44a90 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -2045,6 +2045,13 @@ public class Configuration {
       "server.task.timeout", 1200);
 
   /**
+   * A location of hooks folder relative to resources folder.
+   */
+  @Markdown(description = "A location of hooks folder relative to resources folder.")
+  public static final ConfigurationProperty<String> HOOKS_FOLDER = new ConfigurationProperty<>(
+      "stack.hooks.folder", "stack-hooks");
+
+  /**
    * The location on the Ambari Server where custom actions are defined.
    */
   @Markdown(description = "The location on the Ambari Server where custom actions are defined.")

http://git-wip-us.apache.org/repos/asf/ambari/blob/3dca5607/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index e4dd441..c5303cc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -19,7 +19,6 @@ package org.apache.ambari.server.controller.internal;
 
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
-import static org.apache.ambari.server.stack.StackManager.DEFAULT_HOOKS_FOLDER;
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -977,7 +976,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
           effectiveStackId.getStackVersion(), serviceName);
 
       commandParams.put(SERVICE_PACKAGE_FOLDER, serviceInfo.getServicePackageFolder());
-      commandParams.put(HOOKS_FOLDER, DEFAULT_HOOKS_FOLDER);
+      commandParams.put(HOOKS_FOLDER, s_configuration.getProperty(Configuration.HOOKS_FOLDER));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3dca5607/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
index eb6737a..b11ecab 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
@@ -79,11 +79,6 @@ public class StackManager {
   public static final String COMMON_SERVICES = "common-services";
 
   /**
-   * Prefix used for common stack hooks parent path string
-   */
-  public static final String DEFAULT_HOOKS_FOLDER = "stack-hooks";
-
-  /**
    * Prefix used for extension services parent path string
    */
   public static final String EXTENSIONS = "extensions";

http://git-wip-us.apache.org/repos/asf/ambari/blob/3dca5607/contrib/utils/perf/deploy-gce-perf-cluster.py
----------------------------------------------------------------------
diff --git a/contrib/utils/perf/deploy-gce-perf-cluster.py b/contrib/utils/perf/deploy-gce-perf-cluster.py
index 7431ae9..6084ce9 100644
--- a/contrib/utils/perf/deploy-gce-perf-cluster.py
+++ b/contrib/utils/perf/deploy-gce-perf-cluster.py
@@ -381,6 +381,7 @@ def create_server_script(server_host_name):
   "echo 'alerts.cache.size=100000' >> /etc/ambari-server/conf/ambari.properties\n" + \
   "echo 'alerts.execution.scheduler.maxThreads=4' >> /etc/ambari-server/conf/ambari.properties\n" + \
   "echo 'security.temporary.keystore.retention.minutes=180' >> /etc/ambari-server/conf/ambari.properties\n" + \
+  "echo 'stack.hooks.folder=stacks/PERF/1.0/hooks' >> /etc/ambari-server/conf/ambari.properties\n" + \
   "\n" + \
   "ambari-server start --skip-database-check\n" + \
   "exit 0"


[24/50] [abbrv] ambari git commit: AMBARI-22525 - ATS start failed during patch upgrade due to CNF SparkATSPlugin (jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22525 - ATS start failed during patch upgrade due to CNF SparkATSPlugin (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3fa1289e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3fa1289e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3fa1289e

Branch: refs/heads/branch-3.0-perf
Commit: 3fa1289eaaf9c30985bcf5a50725080a9eb9b368
Parents: 393fdb8
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon Nov 27 13:58:38 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue Nov 28 10:24:31 2017 -0500

----------------------------------------------------------------------
 .../libraries/functions/component_version.py          |  9 +++++----
 .../YARN/2.1.0.2.0/package/scripts/params_linux.py    |  6 ++++++
 .../YARN/3.0.0.3.0/package/scripts/params_linux.py    |  6 ++++++
 .../HDP/2.5/services/YARN/configuration/yarn-site.xml |  4 ++--
 .../stacks/HDP/2.5/services/stack_advisor.py          |  2 +-
 .../stacks/HDP/2.6/upgrades/config-upgrade.xml        | 14 ++++++++++++--
 .../HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml       | 10 ++++++++--
 .../resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml |  4 ++++
 .../HDP/3.0/services/YARN/configuration/yarn-site.xml |  4 ++--
 .../1.0/services/FAKEYARN/configuration/yarn-site.xml |  4 ++--
 .../python/stacks/2.5/common/test_stack_advisor.py    |  2 +-
 11 files changed, 49 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-common/src/main/python/resource_management/libraries/functions/component_version.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/component_version.py b/ambari-common/src/main/python/resource_management/libraries/functions/component_version.py
index 169b339..fd18232 100644
--- a/ambari-common/src/main/python/resource_management/libraries/functions/component_version.py
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/component_version.py
@@ -20,7 +20,7 @@ limitations under the License.
 
 from resource_management.libraries.script.script import Script
 
-def get_component_repository_version(service_name = None, component_name = None):
+def get_component_repository_version(service_name = None, component_name = None, default_value = None):
   """
   Gets the version associated with the specified component from the structure in the command.
   Every command should contain a mapping of service/component to the desired repository it's set
@@ -28,22 +28,23 @@ def get_component_repository_version(service_name = None, component_name = None)
 
   :service_name: the name of the service
   :component_name: the name of the component
+  :default_value: the value to return if either the service or the component are not found
   """
   config = Script.get_config()
 
   versions = _get_component_repositories(config)
   if versions is None:
-    return None
+    return default_value
 
   if service_name is None:
     service_name = config['serviceName'] if config is not None and 'serviceName' in config else None
 
   if service_name is None or service_name not in versions:
-    return None
+    return default_value
 
   component_versions = versions[service_name]
   if len(component_versions) == 0:
-    return None
+    return default_value
 
   if component_name is None:
     component_name = config["role"] if config is not None and "role" in config else None

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py b/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
index 3e4504d..b244af0 100644
--- a/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
+++ b/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
@@ -84,6 +84,12 @@ stack_supports_timeline_state_store = check_stack_feature(StackFeature.TIMELINE_
 # It cannot be used during the initial Cluser Install because the version is not yet known.
 version = default("/commandParams/version", None)
 
+# these are used to render the classpath for picking up Spark classes
+# in the event that spark is not installed, then we must default to the vesrion of YARN installed
+# since it will still load classes from its own spark version
+spark_version = component_version.get_component_repository_version("SPARK", "SPARK_CLIENT", default_value = version)
+spark2_version = component_version.get_component_repository_version("SPARK2", "SPARK2_CLIENT", default_value = version)
+
 stack_supports_ranger_kerberos = check_stack_feature(StackFeature.RANGER_KERBEROS_SUPPORT, version_for_stack_feature_checks)
 stack_supports_ranger_audit_db = check_stack_feature(StackFeature.RANGER_AUDIT_DB_SUPPORT, version_for_stack_feature_checks)
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py b/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
index 617dc3b..372ae85 100644
--- a/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
+++ b/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
@@ -84,6 +84,12 @@ stack_supports_timeline_state_store = check_stack_feature(StackFeature.TIMELINE_
 # It cannot be used during the initial Cluser Install because the version is not yet known.
 version = default("/commandParams/version", None)
 
+# these are used to render the classpath for picking up Spark classes
+# in the event that spark is not installed, then we must default to the vesrion of YARN installed
+# since it will still load classes from its own spark version
+spark_version = component_version.get_component_repository_version("SPARK", "SPARK_CLIENT", default_value = version)
+spark2_version = component_version.get_component_repository_version("SPARK2", "SPARK2_CLIENT", default_value = version)
+
 stack_supports_ranger_kerberos = check_stack_feature(StackFeature.RANGER_KERBEROS_SUPPORT, version_for_stack_feature_checks)
 stack_supports_ranger_audit_db = check_stack_feature(StackFeature.RANGER_AUDIT_DB_SUPPORT, version_for_stack_feature_checks)
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/HDP/2.5/services/YARN/configuration/yarn-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/services/YARN/configuration/yarn-site.xml b/ambari-server/src/main/resources/stacks/HDP/2.5/services/YARN/configuration/yarn-site.xml
index b6fadcb..29833fb 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/services/YARN/configuration/yarn-site.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/services/YARN/configuration/yarn-site.xml
@@ -31,13 +31,13 @@
   </property>
   <property>
     <name>yarn.nodemanager.aux-services.spark_shuffle.classpath</name>
-    <value>{{stack_root}}/${hdp.version}/spark/aux/*</value>
+    <value>{{stack_root}}/{{spark_version}}/spark/aux/*</value>
     <description>The auxiliary service classpath to use for Spark</description>
     <on-ambari-upgrade add="false"/>
   </property>
   <property>
     <name>yarn.nodemanager.aux-services.spark2_shuffle.classpath</name>
-    <value>{{stack_root}}/${hdp.version}/spark2/aux/*</value>
+    <value>{{stack_root}}/{{spark2_version}}/spark2/aux/*</value>
     <description>The auxiliary service classpath to use for Spark 2</description>
     <on-ambari-upgrade add="false"/>
   </property>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/HDP/2.5/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.5/services/stack_advisor.py
index b6f2478..6f409cd 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/services/stack_advisor.py
@@ -823,7 +823,7 @@ class HDP25StackAdvisor(HDP24StackAdvisor):
 
     if self.isServiceDeployed(services, "SPARK"):
       timeline_plugin_classes_values.append('org.apache.spark.deploy.history.yarn.plugin.SparkATSPlugin')
-      timeline_plugin_classpath_values.append(stack_root + "/${hdp.version}/spark/hdpLib/*")
+      timeline_plugin_classpath_values.append(stack_root + "/{{spark_version}}/spark/hdpLib/*")
 
     putYarnSiteProperty('yarn.timeline-service.entity-group-fs-store.group-id-plugin-classes', ",".join(timeline_plugin_classes_values))
     putYarnSiteProperty('yarn.timeline-service.entity-group-fs-store.group-id-plugin-classpath', ":".join(timeline_plugin_classpath_values))

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/config-upgrade.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/config-upgrade.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/config-upgrade.xml
index bcb13bc..9311877 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/config-upgrade.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/config-upgrade.xml
@@ -162,14 +162,13 @@
               if-key-state="absent" />
           </definition>
 
-
           <definition xsi:type="configure" id="hdp_2_6_yarn_app_classpath_parameterization" summary="Application Classpath Parameterization">
             <type>yarn-site</type>
             <replace key="yarn.application.classpath" find="/usr/hdp/current/hadoop-client" replace-with="{{hadoop_home}}"/>
           </definition>
-
         </changes>
       </component>
+
       <component name="NODEMANAGER">
         <changes>
           <definition xsi:type="configure" id="hdp_2_6_0_0_yarn_nodemanager_llap_mem">
@@ -179,6 +178,17 @@
           </definition>
         </changes>
       </component>
+
+      <component name="APP_TIMELINE_SERVER">
+        <changes>
+          <definition xsi:type="configure" id="hdp_2_6_yarn_spark_versioned_classpaths">
+            <type>yarn-site</type>
+            <set key="yarn.nodemanager.aux-services.spark_shuffle.classpath" value="{{stack_root}}/{{spark_version}}/spark/aux/*"/>
+            <set key="yarn.nodemanager.aux-services.spark2_shuffle.classpath" value="{{stack_root}}/{{spark2_version}}/spark2/aux/*"/>
+            <replace key="yarn.timeline-service.entity-group-fs-store.group-id-plugin-classpath" find="${hdp.version}/spark/" replace-with="{{spark_version}}/spark/"/>
+          </definition>
+        </changes>
+      </component>
     </service>
 
     <service name="KAFKA">

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml
index 0355362..2184060 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml
@@ -147,6 +147,7 @@
         <component>DRUID_SUPERSET</component>
       </service>
 
+
     </group>
 
     <group xsi:type="cluster" name="Backups" title="Perform Backups">
@@ -351,7 +352,12 @@
         <task xsi:type="configure" id="hdp_2_6_yarn_app_classpath_parameterization" supports-patch="true"/>
       </execute-stage>
 
-      <!-- YARN -->
+      <execute-stage service="YARN" component="APP_TIMELINE_SERVER" title="Spark Versioned Classpaths">
+        <task xsi:type="configure" id="hdp_2_6_yarn_spark_versioned_classpaths" supports-patch="true">
+          <summary>Updating the Spark classpath entries to use the specific version of Spark which is installed.</summary>
+        </task>
+      </execute-stage>
+
       <execute-stage service="YARN" component="NODEMANAGER" title="Apply config changes for YARN NM">
         <task xsi:type="configure" id="hdp_2_6_0_0_yarn_nodemanager_llap_mem">
           <summary>Updating YARN NodeManager config for LLAP</summary>
@@ -414,7 +420,7 @@
       <execute-stage service="TEZ" component="TEZ_CLIENT" title="Updating LD Library Classpath for Tarball" >
         <task xsi:type="configure" id="hdp_2_6_tez_tarball_ld_library" supports-patch="true"/>
       </execute-stage>
-      
+
       <!-- MapR -->
       <execute-stage service="MAPREDUCE2" component="MAPREDUCE2_CLIENT" title="Updating LD Library Classpath for Tarball">
         <task xsi:type="configure" id="hdp_2_6_mapreduce_tarball_ld_library" supports-patch="true"/>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml
index 5aa2d20..70f84ab 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/upgrades/upgrade-2.6.xml
@@ -690,6 +690,10 @@
 
     <service name="YARN">
       <component name="APP_TIMELINE_SERVER">
+        <pre-upgrade>
+          <task xsi:type="configure" id="hdp_2_6_yarn_spark_versioned_classpaths" supports-patch="true"/>
+        </pre-upgrade>
+        <pre-downgrade/>
         <upgrade>
           <task xsi:type="restart-task" />
         </upgrade>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/HDP/3.0/services/YARN/configuration/yarn-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/3.0/services/YARN/configuration/yarn-site.xml b/ambari-server/src/main/resources/stacks/HDP/3.0/services/YARN/configuration/yarn-site.xml
index 01551c4..d32e2de 100644
--- a/ambari-server/src/main/resources/stacks/HDP/3.0/services/YARN/configuration/yarn-site.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/3.0/services/YARN/configuration/yarn-site.xml
@@ -20,7 +20,7 @@
 
   <property>
     <name>yarn.nodemanager.aux-services.spark_shuffle.classpath</name>
-    <value>{{stack_root}}/${hdp.version}/spark/aux/*</value>
+    <value>{{stack_root}}/{{spark_version}}/spark/aux/*</value>
     <description>The auxiliary service classpath to use for Spark</description>
     <on-ambari-upgrade add="false"/>
   </property>
@@ -41,7 +41,7 @@
   <!-- These configs were inherited from HDP 2.5 -->
   <property>
     <name>yarn.nodemanager.aux-services.spark2_shuffle.classpath</name>
-    <value>{{stack_root}}/${hdp.version}/spark2/aux/*</value>
+    <value>{{stack_root}}/{{spark2_version}}/spark2/aux/*</value>
     <description>The auxiliary service classpath to use for Spark 2</description>
     <on-ambari-upgrade add="false"/>
   </property>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEYARN/configuration/yarn-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEYARN/configuration/yarn-site.xml b/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEYARN/configuration/yarn-site.xml
index 57d03a8..392d0de 100644
--- a/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEYARN/configuration/yarn-site.xml
+++ b/ambari-server/src/main/resources/stacks/PERF/1.0/services/FAKEYARN/configuration/yarn-site.xml
@@ -747,13 +747,13 @@
   </property>
   <property>
     <name>yarn.nodemanager.aux-services.spark_shuffle.classpath</name>
-    <value>{{stack_root}}/${hdp.version}/spark/aux/*</value>
+    <value>{{stack_root}}/{{spark_version}}/spark/aux/*</value>
     <description>The auxiliary service classpath to use for Spark</description>
     <on-ambari-upgrade add="false"/>
   </property>
   <property>
     <name>yarn.nodemanager.aux-services.spark2_shuffle.classpath</name>
-    <value>{{stack_root}}/${hdp.version}/spark2/aux/*</value>
+    <value>{{stack_root}}/{{spark2_version}}/spark2/aux/*</value>
     <description>The auxiliary service classpath to use for Spark 2</description>
     <on-ambari-upgrade add="false"/>
   </property>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3fa1289e/ambari-server/src/test/python/stacks/2.5/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.5/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.5/common/test_stack_advisor.py
index 407e78d..cc6bd9d 100644
--- a/ambari-server/src/test/python/stacks/2.5/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.5/common/test_stack_advisor.py
@@ -1206,7 +1206,7 @@ class TestHDP25StackAdvisor(TestCase):
     self.assertEquals(configurations['hive-interactive-site']['properties']['hive.llap.daemon.queue.name'], 'default')
     self.assertEquals(configurations['yarn-site']['properties']['yarn.timeline-service.entity-group-fs-store.group-id-plugin-classes'],
                       'org.apache.tez.dag.history.logging.ats.TimelineCachePluginImpl,org.apache.spark.deploy.history.yarn.plugin.SparkATSPlugin')
-    self.assertEquals(configurations['yarn-site']['properties']['yarn.timeline-service.entity-group-fs-store.group-id-plugin-classpath'], '/usr/hdp/${hdp.version}/spark/hdpLib/*')
+    self.assertEquals(configurations['yarn-site']['properties']['yarn.timeline-service.entity-group-fs-store.group-id-plugin-classpath'], '/usr/hdp/{{spark_version}}/spark/hdpLib/*')
     self.assertTrue('hive-interactive-env' not in configurations)
     self.assertTrue('property_attributes' not in configurations)
 


[46/50] [abbrv] ambari git commit: AMBARI-22548 Admin View: update toggle styles. (atkach)

Posted by ao...@apache.org.
AMBARI-22548 Admin View: update toggle styles. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c3150a46
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c3150a46
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c3150a46

Branch: refs/heads/branch-3.0-perf
Commit: c3150a4652d8b129383a9a49fc3fd78991b224b7
Parents: 1f7bd75
Author: Andrii Tkach <at...@apache.org>
Authored: Wed Nov 29 19:27:44 2017 +0200
Committer: Andrii Tkach <at...@apache.org>
Committed: Thu Nov 30 12:40:00 2017 +0200

----------------------------------------------------------------------
 .../ui/admin-web/app/styles/toggle-switch.css   | 72 ++++++++++++++++++++
 .../app/views/ambariViews/modals/create.html    |  3 +-
 .../app/views/authentication/main.html          |  6 +-
 .../views/loginActivities/homeDirectory.html    |  6 +-
 .../app/views/loginActivities/loginMessage.html |  6 +-
 .../userManagement/modals/groupCreate.html      |  3 +-
 .../views/userManagement/modals/userCreate.html | 11 ++-
 .../app/views/userManagement/userEdit.html      | 12 ++--
 8 files changed, 104 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/styles/toggle-switch.css
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/styles/toggle-switch.css b/ambari-admin/src/main/resources/ui/admin-web/app/styles/toggle-switch.css
new file mode 100644
index 0000000..3e36a6c
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/styles/toggle-switch.css
@@ -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.
+ */
+
+.ats-switch {
+  border-radius: 20px;
+  height: 40px;
+  min-width: 66px;
+  width: 66px;
+  position: relative;
+  overflow: hidden;
+  border-color: #EBECF1;
+  border-width: 2px;
+}
+
+.ats-switch .knob {
+  margin-left: 34px;
+  border-radius: 20px;
+  height: 32px;
+  width: 32px;
+  margin-top: 2px;
+}
+
+.ats-switch .switch-left,
+.ats-switch .switch-right {
+  position: absolute;
+  right: -40px;
+}
+
+.ats-switch .switch-animate {
+  height: 100%;
+}
+
+.ats-switch .switch-off {
+  background-color: white;
+}
+
+.ats-switch .switch-on {
+  background-color: #1EB475;
+  left: -10%;
+}
+
+.ats-switch .switch-on .knob {
+  background-color: white;
+}
+
+.ats-switch .switch-off .knob {
+  background-color: #999;
+}
+
+.switch-option-label {
+  padding-left: 5px;
+  font-size: 14px;
+}
+
+.switch-inline-label {
+  line-height: 40px;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
index 82f90b3..b9d50c7 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/ambariViews/modals/create.html
@@ -17,7 +17,7 @@
 -->
 <form role="form" id="create-instance-form" name="form.instanceCreateForm" novalidate>
 <div class="modal-header">
-  <h1 class="modal-title">
+  <h1 class="modal-title col-sm-8">
     <span ng-if="!instanceClone">
       {{'views.create' | translate}}
     </span>
@@ -25,6 +25,7 @@
       {{'views.clone' | translate}}
     </span>
   </h1>
+  <a class="close" aria-hidden="true" ng-click="cancel()">&times;</a>
 </div>
 <div class="modal-body" ng-hide="isLoading">
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/authentication/main.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/authentication/main.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/authentication/main.html
index 0275a21..9e672e1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/authentication/main.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/authentication/main.html
@@ -28,9 +28,11 @@
   <div class="form-horizontal">
     <div class="form-group col-sm-12">{{'authentication.description' | translate}}</div>
     <div class="form-group">
-      <label class="control-label col-sm-4">{{'authentication.ldap' | translate}}</label>
+      <label class="switch-inline-label col-sm-4">{{'authentication.ldap' | translate}}</label>
       <span class="col-sm-8">
-        <toggle-switch model="isLDAPEnabled" ng-disabled="isRequestRunning" on-label="{{'authentication.on' | translate}}" off-label="{{'authentication.off' | translate}}" class="switch-primary" data-off-color="danger" on-change="toggleAuthentication()"></toggle-switch>
+        <toggle-switch model="isLDAPEnabled" ng-disabled="isRequestRunning" class="switch-success" data-off-color="danger" on-change="toggleAuthentication()"></toggle-switch>
+        <span ng-if="isLDAPEnabled" class="switch-option-label">{{'authentication.on' | translate}}</span>
+        <span ng-if="!isLDAPEnabled" class="switch-option-label">{{'authentication.off' | translate}}</span>
       </span>
     </div>
   </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/homeDirectory.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/homeDirectory.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/homeDirectory.html
index 913bc0f..7cf17cd 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/homeDirectory.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/homeDirectory.html
@@ -25,9 +25,11 @@
       </div>
       <fieldset>
         <div class="form-group">
-          <label class="col-sm-4 control-label">{{'common.loginActivities.homeDirectory.autoCreate' | translate}}</label>
+          <label class="col-sm-4 switch-inline-label">{{'common.loginActivities.homeDirectory.autoCreate' | translate}}</label>
           <div class="col-sm-8">
-            <toggle-switch model="autoCreate" on-label="{{'common.enabled' | translate}}" off-label="{{'common.disabled' | translate}}" class="switch-primary"></toggle-switch>
+            <toggle-switch model="autoCreate" class="switch-success"></toggle-switch>
+            <span ng-if="autoCreate" class="switch-option-label">{{'common.enabled' | translate}}</span>
+            <span ng-if="!autoCreate" class="switch-option-label">{{'common.disabled' | translate}}</span>
           </div>
           <input type="checkbox" name="autoCreate" class="hidden" ng-model="autoCreate">
         </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/loginMessage.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/loginMessage.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/loginMessage.html
index e5890e5..3055ba1 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/loginMessage.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/loginActivities/loginMessage.html
@@ -22,9 +22,11 @@
     <div class="well">
       <fieldset>
         <div class="form-group">
-          <label class="col-sm-2 control-label">{{'common.loginActivities.status' | translate}}</label>
+          <label class="col-sm-2 switch-inline-label">{{'common.loginActivities.status' | translate}}</label>
           <div class="col-sm-10">
-            <toggle-switch ng-click="changeStatus();" model="status" on-label="{{'common.enabled' | translate}}" off-label="{{'common.disabled' | translate}}" class="switch-primary userstatus" data-off-color="disabled"></toggle-switch>
+            <toggle-switch ng-click="changeStatus();" model="status" class="switch-success" data-off-color="disabled"></toggle-switch>
+            <span ng-if="status" class="switch-option-label">{{'common.enabled' | translate}}</span>
+            <span ng-if="!status" class="switch-option-label">{{'common.disabled' | translate}}</span>
           </div>
           <input type="checkbox" name="status" class="hidden" ng-model="status">
         </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
index e11b478..7692a68 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
@@ -18,9 +18,10 @@
 
 <form id="create-group-form" role="form" novalidate name="form.groupCreateForm">
   <div class="modal-header">
-    <h1 class="modal-title">
+    <h1 class="modal-title col-sm-8">
       {{'groups.createLocal' | translate}}
     </h1>
+    <a class="close" aria-hidden="true" ng-click="cancel()">&times;</a>
   </div>
   <div class="modal-body">
     <div class="form-group"

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
index 2a71102..b1b5876 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
@@ -18,9 +18,10 @@
 
 <form id="create-user-form" role="form" novalidate name="form.userCreateForm">
   <div class="modal-header">
-    <h1 class="modal-title">
+    <h1 class="modal-title col-sm-8">
       {{'users.create' | translate}}
     </h1>
+    <a class="close" aria-hidden="true" ng-click="cancel()">&times;</a>
   </div>
   <div class="modal-body">
     <div class="form-group"
@@ -125,7 +126,9 @@
         <i class="fa fa-question-circle" aria-hidden="true"></i>
       </label>
       <div>
-        <toggle-switch model="formData.isAdmin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary" data-off-color="danger"></toggle-switch>
+        <toggle-switch model="formData.isAdmin" class="switch-success" data-off-color="danger"></toggle-switch>
+        <span ng-if="formData.isAdmin" class="switch-option-label">{{'common.yes' | translate}}</span>
+        <span ng-if="!formData.isAdmin" class="switch-option-label">{{'common.no' | translate}}</span>
       </div>
     </div>
 
@@ -135,7 +138,9 @@
         <i class="fa fa-question-circle" aria-hidden="true"></i>
       </label>
       <div>
-        <toggle-switch model="formData.isActive" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary" data-off-color="danger"></toggle-switch>
+        <toggle-switch model="formData.isActive" class="switch-success" data-off-color="danger"></toggle-switch>
+        <span ng-if="formData.isActive" class="switch-option-label">{{'users.active' | translate}}</span>
+        <span ng-if="!formData.isActive" class="switch-option-label">{{'users.inactive' | translate}}</span>
       </div>
     </div>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c3150a46/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
index cc46173..8a96663 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
@@ -38,15 +38,19 @@
       </div>
     </div>
     <div class="form-group">
-      <label class="col-sm-2 ">{{'users.status' | translate}}</label>
+      <label class="col-sm-2 switch-inline-label">{{'users.status' | translate}}</label>
       <div class="col-sm-10">
-        <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+        <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" class="switch-success userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+        <span ng-if="user.active" class="switch-option-label">{{'users.active' | translate}}</span>
+        <span ng-if="!user.active" class="switch-option-label">{{'users.inactive' | translate}}</span>
       </div>
     </div>
     <div class="form-group">
-      <label class="col-sm-2 "><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
+      <label class="col-sm-2 switch-inline-label"><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
       <div class="col-sm-10">
-        <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+        <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" class="switch-success userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+        <span ng-if="user.admin" class="switch-option-label">{{'common.yes' | translate}}</span>
+        <span ng-if="!user.admin" class="switch-option-label">{{'common.no' | translate}}</span>
       </div>
     </div>
     <div class="form-group">


[36/50] [abbrv] ambari git commit: AMBARI-22480. Validate blueprint does not allow lzo enable without setup with license agreement. Added io.compression.codecs property validation. (mpapirkovskyy)

Posted by ao...@apache.org.
AMBARI-22480. Validate blueprint does not allow lzo enable without setup with license agreement. Added io.compression.codecs property validation. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f6fd9b5c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f6fd9b5c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f6fd9b5c

Branch: refs/heads/branch-3.0-perf
Commit: f6fd9b5c5e04998ed0b0631c87c2d4b521e99a44
Parents: e12efe3
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Tue Nov 28 14:51:58 2017 +0200
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Wed Nov 29 18:30:08 2017 +0200

----------------------------------------------------------------------
 .../server/topology/BlueprintValidatorImpl.java |  4 +++-
 .../server/topology/BlueprintImplTest.java      | 20 +++++++++++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f6fd9b5c/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
index 87b5936..fbd0e4b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
@@ -49,6 +49,7 @@ public class BlueprintValidatorImpl implements BlueprintValidator {
   private final Stack stack;
 
   public static final String LZO_CODEC_CLASS_PROPERTY_NAME = "io.compression.codec.lzo.class";
+  public static final String CODEC_CLASSES_PROPERTY_NAME = "io.compression.codecs";
   public static final String LZO_CODEC_CLASS = "com.hadoop.compression.lzo.LzoCodec";
 
   @Inject
@@ -114,7 +115,8 @@ public class BlueprintValidatorImpl implements BlueprintValidator {
             String propertyName = propertyEntry.getKey();
             String propertyValue = propertyEntry.getValue();
             if (propertyValue != null) {
-              if (!gplEnabled && configType.equals("core-site") && propertyName.equals(LZO_CODEC_CLASS_PROPERTY_NAME)
+              if (!gplEnabled && configType.equals("core-site")
+                  && (propertyName.equals(LZO_CODEC_CLASS_PROPERTY_NAME) || propertyName.equals(CODEC_CLASSES_PROPERTY_NAME))
                   && propertyValue.contains(LZO_CODEC_CLASS)) {
                 throw new GPLLicenseNotAcceptedException("Your Ambari server has not been configured to download LZO GPL software. " +
                     "Please refer to documentation to configure Ambari before proceeding.");

http://git-wip-us.apache.org/repos/asf/ambari/blob/f6fd9b5c/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
index 6d3179e..dd0adcc 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
@@ -299,7 +299,24 @@ public class BlueprintImplTest {
   }
 
   @Test(expected = GPLLicenseNotAcceptedException.class)
-  public void testValidateConfigurations__gplIsNotAllowed() throws InvalidTopologyException,
+  public void testValidateConfigurations__gplIsNotAllowedCodecsProperty() throws InvalidTopologyException,
+      GPLLicenseNotAcceptedException, NoSuchFieldException, IllegalAccessException {
+    Map<String, Map<String, String>> lzoProperties = new HashMap<>();
+    lzoProperties.put("core-site", new HashMap<String, String>(){{
+      put(BlueprintValidatorImpl.CODEC_CLASSES_PROPERTY_NAME, "OtherCodec, " + BlueprintValidatorImpl.LZO_CODEC_CLASS);
+    }});
+    Configuration lzoUsageConfiguration = new Configuration(lzoProperties, EMPTY_ATTRIBUTES, EMPTY_CONFIGURATION);
+
+    org.apache.ambari.server.configuration.Configuration serverConfig = setupConfigurationWithGPLLicense(false);
+    replay(stack, group1, group2, serverConfig);
+
+    Blueprint blueprint = new BlueprintImpl("test", hostGroups, stack, lzoUsageConfiguration, null);
+    blueprint.validateRequiredProperties();
+    verify(stack, group1, group2, serverConfig);
+  }
+
+  @Test(expected = GPLLicenseNotAcceptedException.class)
+  public void testValidateConfigurations__gplIsNotAllowedLZOProperty() throws InvalidTopologyException,
       GPLLicenseNotAcceptedException, NoSuchFieldException, IllegalAccessException {
     Map<String, Map<String, String>> lzoProperties = new HashMap<>();
     lzoProperties.put("core-site", new HashMap<String, String>(){{
@@ -321,6 +338,7 @@ public class BlueprintImplTest {
     Map<String, Map<String, String>> lzoProperties = new HashMap<>();
     lzoProperties.put("core-site", new HashMap<String, String>(){{
       put(BlueprintValidatorImpl.LZO_CODEC_CLASS_PROPERTY_NAME, BlueprintValidatorImpl.LZO_CODEC_CLASS);
+      put(BlueprintValidatorImpl.CODEC_CLASSES_PROPERTY_NAME, "OtherCodec, " + BlueprintValidatorImpl.LZO_CODEC_CLASS);
     }});
     Configuration lzoUsageConfiguration = new Configuration(lzoProperties, EMPTY_ATTRIBUTES, EMPTY_CONFIGURATION);
 


[32/50] [abbrv] ambari git commit: AMBARI-22534 Package install fails with HDP-2.5.3/2.6.4.0 version at atlas falcon plugin install (dgrinenko)

Posted by ao...@apache.org.
AMBARI-22534 Package install fails with HDP-2.5.3/2.6.4.0 version at atlas falcon plugin install (dgrinenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0cf82767
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0cf82767
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0cf82767

Branch: refs/heads/branch-3.0-perf
Commit: 0cf82767c8f90ff858b678dde98c3eaba7d1fad4
Parents: 7fd404a
Author: Dmytro Grinenko <ha...@apache.org>
Authored: Wed Nov 29 11:04:54 2017 +0200
Committer: Dmytro Grinenko <ha...@apache.org>
Committed: Wed Nov 29 11:07:26 2017 +0200

----------------------------------------------------------------------
 .../stacks/HDP/2.5/services/FALCON/metainfo.xml |  4 +--
 .../stacks/HDP/2.6/services/FALCON/metainfo.xml | 26 ++++++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/0cf82767/ambari-server/src/main/resources/stacks/HDP/2.5/services/FALCON/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/services/FALCON/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.5/services/FALCON/metainfo.xml
index 1066f6c..79296c3 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/services/FALCON/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/services/FALCON/metainfo.xml
@@ -30,7 +30,7 @@
               <name>falcon_${stack_version}</name>
             </package>
             <package>
-              <name>atlas-metadata_${stack_version}-falcon-plugin</name>
+              <name>atlas-metadata_${stack_version}-hive-plugin</name>
               <condition>should_install_falcon_atlas_hook</condition>
             </package>
           </packages>
@@ -42,7 +42,7 @@
               <name>falcon-${stack_version}</name>
             </package>
             <package>
-              <name>atlas-metadata-${stack_version}-falcon-plugin</name>
+              <name>atlas-metadata-${stack_version}-hive-plugin</name>
               <condition>should_install_falcon_atlas_hook</condition>
             </package>
           </packages>

http://git-wip-us.apache.org/repos/asf/ambari/blob/0cf82767/ambari-server/src/main/resources/stacks/HDP/2.6/services/FALCON/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/services/FALCON/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/services/FALCON/metainfo.xml
index fdeca9b..c4a0c98 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/services/FALCON/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/services/FALCON/metainfo.xml
@@ -21,6 +21,32 @@
     <service>
       <name>FALCON</name>
       <version>0.10.0</version>
+      <osSpecifics>
+        <osSpecific>
+          <osFamily>redhat7,amazon2015,redhat6,suse11,suse12</osFamily>
+          <packages>
+            <package>
+              <name>falcon_${stack_version}</name>
+            </package>
+            <package>
+              <name>atlas-metadata_${stack_version}-falcon-plugin</name>
+              <condition>should_install_falcon_atlas_hook</condition>
+            </package>
+          </packages>
+        </osSpecific>
+        <osSpecific>
+          <osFamily>debian7,ubuntu12,ubuntu14,ubuntu16</osFamily>
+          <packages>
+            <package>
+              <name>falcon-${stack_version}</name>
+            </package>
+            <package>
+              <name>atlas-metadata-${stack_version}-falcon-plugin</name>
+              <condition>should_install_falcon_atlas_hook</condition>
+            </package>
+          </packages>
+        </osSpecific>
+      </osSpecifics>
     </service>
   </services>
 </metainfo>


[13/50] [abbrv] ambari git commit: AMBARI-22519 Admin View: add ability to change roles. (atkach)

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
index 0372a11..cc46173 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
@@ -16,13 +16,13 @@
 * limitations under the License.
 -->
     
-<div ng-show="user" class="user-edit-panel">
+<div ng-show="user" id="user-edit">
   <div class="clearfix">
     <ol class="breadcrumb pull-left">
-      <li><a href="#/userManagement">{{'common.users' | translate}}</a></li>
+      <li><a href="#/userManagement?tab=users">{{'common.users' | translate}}</a></li>
       <li class="active"><span class="glyphicon glyphicon-flash" ng-show="user.admin"></span>{{user.user_name}}</li>
     </ol>
-    <div class="pull-right top-margin-4">
+    <div class="pull-right">
       <div ng-switch="isCurrentUser || user.user_type != 'LOCAL'">
         <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'common.cannotDelete' | translate: '{term: constants.user}'}}">{{'common.delete' | translate: '{term: constants.user}'}}</button>
         <button class="btn deleteuser-btn btn-danger" ng-switch-when="false" ng-click="deleteUser()">{{'common.delete' | translate: '{term: constants.user}'}}</button>
@@ -32,25 +32,25 @@
   <hr>
   <form class="form-horizontal" role="form" >
     <div class="form-group">
-      <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+      <label class="col-sm-2 ">{{'common.type' | translate}}</label>
       <div class="col-sm-10">
-        <label for="" class="control-label">{{user.userTypeName}}</label>
+        <label>{{user.userTypeName}}</label>
       </div>
     </div>
     <div class="form-group">
-      <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
+      <label class="col-sm-2 ">{{'users.status' | translate}}</label>
       <div class="col-sm-10">
         <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
       </div>
     </div>
     <div class="form-group">
-      <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
+      <label class="col-sm-2 "><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
       <div class="col-sm-10">
         <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
       </div>
     </div>
     <div class="form-group">
-      <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
+      <label class="col-sm-2 ">{{'users.password' | translate}}</label>
       <div class="col-sm-10">
         <div ng-switch="user.user_type != 'LOCAL'">
           <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.password}'}}">{{'users.changePassword' | translate}}</button>
@@ -60,14 +60,32 @@
       </div>
     </div>
     <div class="form-group">
-      <label for="groups" class="col-sm-2 control-label">{{getUserMembership(user.user_type)}}</label>
+      <label class="col-sm-2 ">{{getUserMembership(user.user_type)}}</label>
       <div class="col-sm-10">
         <editable-list items-source="editingGroupsList" resource-type="Group" editable="user.user_type == 'LOCAL'"></editable-list>
       </div>
-        
     </div>
+
+    <div class="form-group">
+      <label for="role" class="col-sm-2 roles-label">
+        {{'users.role' | translate}}
+        <i class="fa fa-question-circle" aria-hidden="true" ng-click="showHelpPage()"></i>
+      </label>
+      <div class="col-sm-3">
+        <select ng-hide="user.admin"
+                class="form-control"
+                id="role"
+                name="role"
+                ng-options="item as item.permission_label for item in roleOptions track by item.permission_name"
+                ng-change="updateRole()"
+                ng-model="currentRole">
+        </select>
+        <span ng-show="user.admin" class="roles-label">{{user.roles[0].permission_label}}</span>
+      </div>
+    </div>
+
     <div class="form-group" >
-      <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
+      <label class="col-sm-2 ">{{'common.privileges' | translate}}</label>
       <div class="col-sm-10">
         <table class="table" ng-hide="hidePrivileges || user.admin">
           <thead>
@@ -77,7 +95,7 @@
             </tr>
           </thead>
           <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.clusters">
+            <tr ng-repeat="(name, privilege) in privilegesView.clusters">
               <td>
                 <span class="glyphicon glyphicon-cloud"></span> 
                 <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
@@ -97,7 +115,7 @@
             </tr>
           </thead>
           <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.views">
+            <tr ng-repeat="(name, privilege) in privilegesView.views">
               <td>
                 <span class="glyphicon glyphicon-th"></span>
                 <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
@@ -106,7 +124,7 @@
                 <span tooltip="{{item}}" ng-repeat="item in privilege.privileges track by $index">{{item | translate}}{{$last ? '' : ', '}}</span>
               </td>
               <td>
-                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
+                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removeViewPrivilege(name, privilege);"></i>
               </td>
             </tr>
             <tr>
@@ -114,7 +132,7 @@
             </tr>
           </tbody>
         </table>
-        <div class="alert alert-info" ng-show="!privileges && !user.admin">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.user}'}}</div>
+        <div class="alert alert-info" ng-show="hidePrivileges && !user.admin">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.user}'}}</div>
         <div class="alert alert-info" ng-show="user.admin">{{'users.userIsAdmin' | translate}}</div>
       </div>
     </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/32e25b80/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
index cc4789b..4a33a31 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
@@ -78,7 +78,7 @@
           <span>{{user.Users.user_name}}</span>
         </td>
         <td>
-          <span>{{user.Users.role}}</span>
+          <span>{{user.Users.roles[0].permission_label}}</span>
         </td>
         <td>
           <span>


[03/50] [abbrv] ambari git commit: AMBARI-22502.Workflow Manager View - FS node will overwrite internal commands and replace them with blank "move" commands when reopening the node(Venkata Sairam)

Posted by ao...@apache.org.
AMBARI-22502.Workflow Manager View - FS node will overwrite internal commands and replace them with blank "move" commands when reopening the node(Venkata Sairam)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/51360219
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/51360219
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/51360219

Branch: refs/heads/branch-3.0-perf
Commit: 51360219866386d8103326def2a1d412348414ed
Parents: 20dee7f
Author: Venkata Sairam <ve...@gmail.com>
Authored: Thu Nov 23 15:36:57 2017 +0530
Committer: Venkata Sairam <ve...@gmail.com>
Committed: Thu Nov 23 15:36:57 2017 +0530

----------------------------------------------------------------------
 .../src/main/resources/ui/app/domain/workflow-importer.js         | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/51360219/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
index 84a789d..2afc304 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
@@ -112,7 +112,8 @@ var WorkflowImporter= Ember.Object.extend({
       if (nodeHandler){
         if (Ember.isArray(workflowAppJson[key])){
           workflowAppJson[key].forEach(function(jsonObj){
-            var node=nodeHandler.handleImportNode(key,jsonObj,workflow,xmlDoc);
+            var actionDom = xmlDoc.find("action[name='" + jsonObj._name + "']");
+            var node = nodeHandler.handleImportNode(key,jsonObj,workflow,actionDom);
             nodeMap.set(jsonObj._name,{json:jsonObj,node:node});
           });
         }else{


[27/50] [abbrv] ambari git commit: AMBARI-22465 Post-Upgrade Tasks Use the Wrong Repository and Hooks Folders (dgrinenko)

Posted by ao...@apache.org.
AMBARI-22465 Post-Upgrade Tasks Use the Wrong Repository and Hooks Folders (dgrinenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/82af6fb6
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/82af6fb6
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/82af6fb6

Branch: refs/heads/branch-3.0-perf
Commit: 82af6fb6d3f11476df203d9871cc978091891cfe
Parents: 020e152
Author: Dmytro Grinenko <ha...@apache.org>
Authored: Tue Nov 28 19:23:28 2017 +0200
Committer: Dmytro Grinenko <ha...@apache.org>
Committed: Tue Nov 28 19:25:28 2017 +0200

----------------------------------------------------------------------
 .../server/controller/internal/UpgradeResourceProvider.java  | 8 --------
 .../resources/custom_actions/scripts/ru_execute_tasks.py     | 5 +++--
 .../src/test/python/custom_actions/test_ru_execute_tasks.py  | 6 +++---
 3 files changed, 6 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/82af6fb6/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index c5303cc..bab5369 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -1053,10 +1053,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     // Apply additional parameters to the command that come from the stage.
     applyAdditionalParameters(wrapper, params);
 
-    // the ru_execute_tasks invokes scripts - it needs information about where
-    // the scripts live and for that it should always use the target repository
-    // stack
-    applyRepositoryAssociatedParameters(wrapper, effectiveRepositoryVersion.getStackId(), params);
 
     // add each host to this stage
     RequestResourceFilter filter = new RequestResourceFilter(serviceName, componentName,
@@ -1204,10 +1200,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     // Apply additional parameters to the command that come from the stage.
     applyAdditionalParameters(wrapper, commandParams);
 
-    // add things like hooks and service folders based on effective repo
-    applyRepositoryAssociatedParameters(wrapper, effectiveRepositoryVersion.getStackId(),
-        commandParams);
-
     ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
         "SERVICE_CHECK", filters, commandParams);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/82af6fb6/ambari-server/src/main/resources/custom_actions/scripts/ru_execute_tasks.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/custom_actions/scripts/ru_execute_tasks.py b/ambari-server/src/main/resources/custom_actions/scripts/ru_execute_tasks.py
index c0f0d41..dff4ee1 100644
--- a/ambari-server/src/main/resources/custom_actions/scripts/ru_execute_tasks.py
+++ b/ambari-server/src/main/resources/custom_actions/scripts/ru_execute_tasks.py
@@ -102,8 +102,8 @@ class ExecuteUpgradeTasks(Script):
     version = default('/roleParams/version', None)
 
     # These 2 variables are optional
-    service_package_folder = default('/roleParams/service_package_folder', None)
-    hooks_folder = default('/roleParams/hooks_folder', None)
+    service_package_folder = default('/commandParams/service_package_folder', None)
+    hooks_folder = default('/commandParams/hooks_folder', None)
 
     tasks = json.loads(config['roleParams']['tasks'])
     if tasks:
@@ -154,5 +154,6 @@ class ExecuteUpgradeTasks(Script):
           task.command = replace_variables(task.command, host_name, version)
           shell.checked_call(task.command, logoutput=True, quiet=True)
 
+
 if __name__ == "__main__":
   ExecuteUpgradeTasks().execute()

http://git-wip-us.apache.org/repos/asf/ambari/blob/82af6fb6/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py b/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
index 0d12a91..17d5e77 100644
--- a/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
+++ b/ambari-server/src/test/python/custom_actions/test_ru_execute_tasks.py
@@ -146,8 +146,8 @@ class TestRUExecuteTasks(RMFTestCase):
     with open(json_file_path, "r") as json_file:
       json_payload = json.load(json_file)
 
-    del json_payload['roleParams']['service_package_folder']
-    del json_payload['roleParams']['hooks_folder']
+    del json_payload['commandParams']['service_package_folder']
+    del json_payload['commandParams']['hooks_folder']
 
     config_dict = ConfigDictionary(json_payload)
 
@@ -166,7 +166,7 @@ class TestRUExecuteTasks(RMFTestCase):
     # Ensure that the json file was actually read.
     stack_name = default("/hostLevelParams/stack_name", None)
     stack_version = default("/hostLevelParams/stack_version", None)
-    service_package_folder = default('/roleParams/service_package_folder', None)
+    service_package_folder = default('/commandParams/service_package_folder', None)
 
     self.assertEqual(stack_name, "HDP")
     self.assertEqual(stack_version, '2.2')


[41/50] [abbrv] ambari git commit: AMBARI-22547 - History and Hive server start failed during IOP migration with AttributeError (jonathanhurley)

Posted by ao...@apache.org.
AMBARI-22547 - History and Hive server start failed during IOP migration with AttributeError (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/323ce7a7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/323ce7a7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/323ce7a7

Branch: refs/heads/branch-3.0-perf
Commit: 323ce7a797a65f795382c815a4068ae4b1e94bbb
Parents: 0d7f609
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Wed Nov 29 11:51:47 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Wed Nov 29 16:18:57 2017 -0500

----------------------------------------------------------------------
 .../libraries/functions/copy_tarball.py                   | 10 ++++++++--
 .../YARN/2.1.0.2.0/package/scripts/params_linux.py        |  4 ++--
 .../YARN/3.0.0.3.0/package/scripts/params_linux.py        |  4 ++--
 3 files changed, 12 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/323ce7a7/ambari-common/src/main/python/resource_management/libraries/functions/copy_tarball.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/copy_tarball.py b/ambari-common/src/main/python/resource_management/libraries/functions/copy_tarball.py
index c15fbd1..18800db 100644
--- a/ambari-common/src/main/python/resource_management/libraries/functions/copy_tarball.py
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/copy_tarball.py
@@ -90,8 +90,14 @@ def _prepare_tez_tarball():
   # if enabled, LZO GPL libraries must be copied as well
   if lzo_utils.should_install_lzo():
     stack_root = Script.get_stack_root()
-    tez_version = component_version.get_component_repository_version("TEZ")
-    hadoop_lib_native_lzo_dir = os.path.join(stack_root, tez_version, "hadoop", "lib", "native")
+    service_version = component_version.get_component_repository_version(service_name = "TEZ")
+
+    # some installations might not have Tez, but MapReduce2 should be a fallback to get the LZO libraries from
+    if service_version is None:
+      Logger.warning("Tez does not appear to be installed, using the MapReduce version to get the LZO libraries")
+      service_version = component_version.get_component_repository_version(service_name = "MAPREDUCE2")
+
+    hadoop_lib_native_lzo_dir = os.path.join(stack_root, service_version, "hadoop", "lib", "native")
 
     if not sudo.path_isdir(hadoop_lib_native_lzo_dir):
       Logger.warning("Unable to located native LZO libraries at {0}, falling back to hadoop home".format(hadoop_lib_native_lzo_dir))

http://git-wip-us.apache.org/repos/asf/ambari/blob/323ce7a7/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py b/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
index b244af0..1bc01d4 100644
--- a/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
+++ b/ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/package/scripts/params_linux.py
@@ -87,8 +87,8 @@ version = default("/commandParams/version", None)
 # these are used to render the classpath for picking up Spark classes
 # in the event that spark is not installed, then we must default to the vesrion of YARN installed
 # since it will still load classes from its own spark version
-spark_version = component_version.get_component_repository_version("SPARK", "SPARK_CLIENT", default_value = version)
-spark2_version = component_version.get_component_repository_version("SPARK2", "SPARK2_CLIENT", default_value = version)
+spark_version = component_version.get_component_repository_version(service_name =  "SPARK", component_name = "SPARK_CLIENT", default_value = version)
+spark2_version = component_version.get_component_repository_version(service_name = "SPARK2", component_name = "SPARK2_CLIENT", default_value = version)
 
 stack_supports_ranger_kerberos = check_stack_feature(StackFeature.RANGER_KERBEROS_SUPPORT, version_for_stack_feature_checks)
 stack_supports_ranger_audit_db = check_stack_feature(StackFeature.RANGER_AUDIT_DB_SUPPORT, version_for_stack_feature_checks)

http://git-wip-us.apache.org/repos/asf/ambari/blob/323ce7a7/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py b/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
index 372ae85..b8a5382 100644
--- a/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
+++ b/ambari-server/src/main/resources/common-services/YARN/3.0.0.3.0/package/scripts/params_linux.py
@@ -87,8 +87,8 @@ version = default("/commandParams/version", None)
 # these are used to render the classpath for picking up Spark classes
 # in the event that spark is not installed, then we must default to the vesrion of YARN installed
 # since it will still load classes from its own spark version
-spark_version = component_version.get_component_repository_version("SPARK", "SPARK_CLIENT", default_value = version)
-spark2_version = component_version.get_component_repository_version("SPARK2", "SPARK2_CLIENT", default_value = version)
+spark_version = component_version.get_component_repository_version(service_name =  "SPARK", component_name = "SPARK_CLIENT", default_value = version)
+spark2_version = component_version.get_component_repository_version(service_name = "SPARK2", component_name = "SPARK2_CLIENT", default_value = version)
 
 stack_supports_ranger_kerberos = check_stack_feature(StackFeature.RANGER_KERBEROS_SUPPORT, version_for_stack_feature_checks)
 stack_supports_ranger_audit_db = check_stack_feature(StackFeature.RANGER_AUDIT_DB_SUPPORT, version_for_stack_feature_checks)


[06/50] [abbrv] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
new file mode 100644
index 0000000..e0c1144
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/groupCreate.html
@@ -0,0 +1,86 @@
+<!--
+* 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.
+-->
+
+<form id="create-group-form" role="form" novalidate name="form.groupCreateForm">
+  <div class="modal-header">
+    <h1 class="modal-title">
+      {{'groups.createLocal' | translate}}
+    </h1>
+  </div>
+  <div class="modal-body">
+    <div class="form-group"
+         ng-class="{ 'has-error': (form.groupCreateForm.groupName.$error.required || form.groupCreateForm.groupName.$error.pattern) && form.groupCreateForm.submitted }">
+      <label for="groupName">
+        {{'groups.name' | translate}}<span>&nbsp;*</span>&nbsp;
+      </label>
+      <input type="text"
+             placeholder="{{'groups.name' | translate}}"
+             ng-pattern="/^([a-zA-Z0-9._\s]+)$/"
+             autofocus
+             ng-maxlength="80"
+             autocomplete="off"
+             class="form-control"
+             ng-model="formData.groupName"
+             name="groupName"
+             id="groupName"
+             ng-change="checkIfInstanceExist()"
+             required>
+      <span class="help-block validation-block"
+            ng-show='form.groupCreateForm.groupName.$error.required && form.groupCreateForm.submitted'>
+        {{'common.alerts.fieldRequired' | translate}}
+      </span>
+      <span class="help-block validation-block"
+            ng-show='form.groupCreateForm.groupName.$error.pattern && form.groupCreateForm.submitted'>
+        {{'common.alerts.noSpecialChars' | translate}}
+      </span>
+    </div>
+
+    <div class="form-group">
+      <label>{{'groups.addUsers' | translate}}</label>
+      <div>
+        <editable-list items-source="formData.members" resource-type="User" editable="true"></editable-list>
+      </div>
+    </div>
+
+    <div class="row">
+      <div class="form-group col-sm-6"
+           ng-class="{ 'has-error': form.groupCreateForm.role.$error.required && form.groupCreateForm.submitted }">
+        <label for="role" class="nowrap">
+          {{'groups.role' | translate}}
+          <i class="fa fa-question-circle" aria-hidden="true"></i>
+        </label>
+        <select
+          class="form-control"
+          id="role"
+          name="role"
+          ng-model="formData.role">
+          <option value="" disabled selected>{{'common.select' | translate}}</option>
+          <option ng-repeat="role in roleOptions" value="{{role.permission_id}}">{{role.permission_label}}</option>
+        </select>
+        <span class="help-block validation-block" ng-show='form.groupCreateForm.role.$error.required && form.groupCreateForm.submitted'>
+          {{'common.alerts.fieldRequired' | translate}}
+        </span>
+      </div>
+    </div>
+
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+    <button class="btn btn-primary" ng-click="save()" type="submit">{{'common.controls.save' | translate}}</button>
+  </div>
+</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
new file mode 100644
index 0000000..0af26eb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/modals/userCreate.html
@@ -0,0 +1,147 @@
+<!--
+* 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.
+-->
+
+<form id="create-user-form" role="form" novalidate name="form.userCreateForm">
+  <div class="modal-header">
+    <h1 class="modal-title">
+      {{'users.create' | translate}}
+    </h1>
+  </div>
+  <div class="modal-body">
+    <div class="form-group"
+         ng-class="{ 'has-error': (form.userCreateForm.userName.$error.required || form.userCreateForm.userName.$error.pattern) && form.userCreateForm.submitted }">
+      <label for="userName">
+        {{'users.username' | translate}}<span>&nbsp;*</span>&nbsp;
+        <i class="fa fa-question-circle" aria-hidden="true"></i>
+      </label>
+      <input type="text"
+             autofocus
+             placeholder="{{'users.user.name' | translate}}"
+             ng-pattern="/^[^<>&`|\\]+$/"
+             ng-maxlength="80"
+             tooltip="{{'users.userNameTip' | translate}}"
+             autocomplete="off"
+             tooltip-trigger="focus"
+             class="form-control"
+             ng-model="formData.userName"
+             name="userName"
+             id="userName"
+             ng-change="checkIfInstanceExist()"
+             required>
+      <span class="help-block validation-block"
+            ng-show='form.userCreateForm.userName.$error.required && form.userCreateForm.submitted'>
+        {{'common.alerts.fieldRequired' | translate}}
+      </span>
+      <span class="help-block validation-block"
+            ng-show='form.userCreateForm.userName.$error.pattern && form.userCreateForm.submitted'>
+        {{'common.alerts.noSpecialChars' | translate}}
+      </span>
+    </div>
+
+    <div class="row">
+      <div class="form-group col-sm-6"
+           ng-class="{ 'has-error': form.userCreateForm.password.$error.required && form.userCreateForm.submitted }">
+        <label for="password">
+          {{'users.password' | translate}}<span>&nbsp;*</span>
+        </label>
+        <input type="password"
+               id="password"
+               class="form-control"
+               name="password"
+               placeholder="{{'users.password' | translate}}"
+               required
+               ng-model="formData.password"
+               autocomplete="off">
+        <span class="help-block validation-block"
+              ng-show='form.userCreateForm.password.$error.required && form.userCreateForm.submitted'>
+          {{'common.alerts.fieldRequired' | translate}}
+        </span>
+      </div>
+      <div class="form-group col-sm-6"
+           ng-class="{ 'has-error': form.userCreateForm.confirmPassword.$error.passwordVerify || (form.userCreateForm.confirmPassword.$error.required && form.userCreateForm.submitted) }">
+        <label for="confirmPassword">
+          {{'users.confirmPassword' | translate}}<span>&nbsp;*</span>
+        </label>
+        <input type="password"
+               id="confirmPassword"
+               class="form-control"
+               name="confirmPassword"
+               placeholder="{{'users.confirmPassword' | translate}}"
+               required
+               password-verify="formData.password"
+               ng-model="formData.confirmPassword"
+               autocomplete="off">
+        <span class="help-block validation-block"
+              ng-show='form.userCreateForm.confirmPassword.$error.required && form.userCreateForm.submitted'>
+          {{'common.alerts.fieldRequired' | translate}}
+        </span>
+        <span class="help-block validation-block"
+              ng-show='form.userCreateForm.confirmPassword.$error.passwordVerify'>
+          {{'users.alerts.wrongPassword' | translate}}
+        </span>
+      </div>
+    </div>
+
+    <div class="row">
+      <div class="form-group col-sm-6"
+           ng-class="{ 'has-error': form.userCreateForm.role.$error.required && form.userCreateForm.submitted }">
+        <label for="role" class="nowrap">
+          {{'users.role' | translate}}<span>&nbsp;*</span>&nbsp;
+          <i class="fa fa-question-circle" aria-hidden="true"></i>
+        </label>
+        <select
+          class="form-control"
+          id="role"
+          name="role"
+          ng-model="formData.role"
+          required>
+          <option value="" disabled selected>{{'common.select' | translate}}</option>
+          <option ng-repeat="role in roleOptions" value="{{role.permission_id}}">{{role.permission_label}}</option>
+        </select>
+        <span class="help-block validation-block" ng-show='form.userCreateForm.role.$error.required && form.userCreateForm.submitted'>
+          {{'common.alerts.fieldRequired' | translate}}
+        </span>
+      </div>
+    </div>
+
+    <div class="form-group">
+      <label>
+        {{'users.isAmbariAdmin' | translate}}<span>&nbsp;*</span>
+        <i class="fa fa-question-circle" aria-hidden="true"></i>
+      </label>
+      <div>
+        <toggle-switch model="formData.isAdmin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary" data-off-color="danger"></toggle-switch>
+      </div>
+    </div>
+
+    <div class="form-group">
+      <label>
+        {{'users.isActive' | translate}}<span>&nbsp;*</span>
+        <i class="fa fa-question-circle" aria-hidden="true"></i>
+      </label>
+      <div>
+        <toggle-switch model="formData.isActive" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary" data-off-color="danger"></toggle-switch>
+      </div>
+    </div>
+
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
+    <button class="btn btn-primary" ng-click="save()" type="submit">{{'common.controls.save' | translate}}</button>
+  </div>
+</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
new file mode 100644
index 0000000..0372a11
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/userEdit.html
@@ -0,0 +1,122 @@
+<!--
+* 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 ng-show="user" class="user-edit-panel">
+  <div class="clearfix">
+    <ol class="breadcrumb pull-left">
+      <li><a href="#/userManagement">{{'common.users' | translate}}</a></li>
+      <li class="active"><span class="glyphicon glyphicon-flash" ng-show="user.admin"></span>{{user.user_name}}</li>
+    </ol>
+    <div class="pull-right top-margin-4">
+      <div ng-switch="isCurrentUser || user.user_type != 'LOCAL'">
+        <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'common.cannotDelete' | translate: '{term: constants.user}'}}">{{'common.delete' | translate: '{term: constants.user}'}}</button>
+        <button class="btn deleteuser-btn btn-danger" ng-switch-when="false" ng-click="deleteUser()">{{'common.delete' | translate: '{term: constants.user}'}}</button>
+      </div>
+    </div>
+  </div>
+  <hr>
+  <form class="form-horizontal" role="form" >
+    <div class="form-group">
+      <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
+      <div class="col-sm-10">
+        <label for="" class="control-label">{{user.userTypeName}}</label>
+      </div>
+    </div>
+    <div class="form-group">
+      <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
+      <div class="col-sm-10">
+        <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+      </div>
+    </div>
+    <div class="form-group">
+      <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
+      <div class="col-sm-10">
+        <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
+      </div>
+    </div>
+    <div class="form-group">
+      <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
+      <div class="col-sm-10">
+        <div ng-switch="user.user_type != 'LOCAL'">
+          <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.password}'}}">{{'users.changePassword' | translate}}</button>
+          <a href ng-click="openChangePwdDialog()" ng-switch-when="false" class="btn btn-default changepassword">{{'users.changePassword' | translate}}</a>
+        </div>
+          
+      </div>
+    </div>
+    <div class="form-group">
+      <label for="groups" class="col-sm-2 control-label">{{getUserMembership(user.user_type)}}</label>
+      <div class="col-sm-10">
+        <editable-list items-source="editingGroupsList" resource-type="Group" editable="user.user_type == 'LOCAL'"></editable-list>
+      </div>
+        
+    </div>
+    <div class="form-group" >
+      <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
+      <div class="col-sm-10">
+        <table class="table" ng-hide="hidePrivileges || user.admin">
+          <thead>
+            <tr>
+              <th>{{'common.cluster' | translate}}</th>
+              <th>{{'common.clusterRole' | translate}}</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr ng-repeat="(name, privilege) in privileges.clusters">
+              <td>
+                <span class="glyphicon glyphicon-cloud"></span> 
+                <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
+              </td>
+              <td>
+                <span tooltip="{{privilege.permission_label}}">{{privilege.permission_label}}</span>
+              </td>
+            </tr>
+            <tr>
+              <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
+            </tr>
+          </tbody>
+          <thead class="view-permission-header">
+            <tr>
+              <th>{{'common.view' | translate}}</th>
+              <th>{{'common.viewPermissions' | translate}}</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr ng-repeat="(name, privilege) in privileges.views">
+              <td>
+                <span class="glyphicon glyphicon-th"></span>
+                <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
+              </td>
+              <td>
+                <span tooltip="{{item}}" ng-repeat="item in privilege.privileges track by $index">{{item | translate}}{{$last ? '' : ', '}}</span>
+              </td>
+              <td>
+                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
+              </td>
+            </tr>
+            <tr>
+              <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="alert alert-info" ng-show="!privileges && !user.admin">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.user}'}}</div>
+        <div class="alert alert-info" ng-show="user.admin">{{'users.userIsAdmin' | translate}}</div>
+      </div>
+    </div>
+  </form>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
new file mode 100644
index 0000000..cc4789b
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/userManagement/usersList.html
@@ -0,0 +1,119 @@
+<!--
+* 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="users-pane">
+  <div class="clearfix panel">
+    <button class="btn btn-default createuser-btn pull-right" ng-click="createUser();">
+      {{'users.create' | translate}}
+    </button>
+  </div>
+  <table class="table table-striped table-hover">
+    <thead>
+      <tr class="fix-bottom">
+        <th>
+          <span>{{'users.username' | translate}}</span>
+        </th>
+        <th>
+          <span>{{'clusters.role' | translate}}</span>
+        </th>
+        <th>
+          <span>{{'users.status' | translate}}</span>
+        </th>
+        <th>
+          <span>{{'common.type' | translate}}</span>
+        </th>
+        <th>
+          <span>{{'common.group' | translate}}</span>
+        </th>
+        <th class="entity-actions">
+          <span>{{'common.actions' | translate}}</span>
+        </th>
+      </tr>
+      <tr class="fix-top">
+        <th>
+          <div class="search-container">
+            <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="filters.name" ng-change="resetPagination()">
+            <button type="button" class="close clearfilter" ng-show="filters.name" ng-click="filters.name=''; resetPagination()">
+              <span aria-hidden="true">&times;</span><span class="sr-only">{{'common.controls.close' | translate}}</span>
+            </button>
+          </div>
+        </th>
+        <th></th>
+        <th>
+          <select class="form-control statusfilter"
+                  ng-model="filters.status"
+                  ng-options="item.label for item in activeFilterOptions"
+                  ng-change="resetPagination()">
+          </select>
+        </th>
+        <th>
+          <select class="form-control typefilter"
+                  ng-model="filters.type"
+                  ng-options="item.label for item in typeFilterOptions"
+                  ng-change="resetPagination()">
+          </select>
+        </th>
+        <th></th>
+        <th></th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr ng-repeat="user in users">
+        <td>
+          <span>{{user.Users.user_name}}</span>
+        </td>
+        <td>
+          <span>{{user.Users.role}}</span>
+        </td>
+        <td>
+          <span>
+            {{(user.Users.active ? 'users.active' : 'users.inactive') | translate}}
+          </span>
+        </td>
+        <td><span>{{user.Users.userTypeName}}</span></td>
+        <td><span>{{user.Users.groups.length ? user.Users.groups.join(' ') : '-'}}</span></td>
+        <td class="entity-actions">
+          <a href="#/users/{{user.Users.encodedName}}/edit">
+            <i class="fa fa-pencil"></i>
+          </a>
+          <a href ng-click="deleteUser(user.Users)">
+            <i class="fa fa-trash-o"></i>
+          </a>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+  <div ng-if="isLoading" class="spinner-container">
+    <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
+  </div>
+  <div class="alert empty-table-alert col-sm-12" ng-show="!users.length && !isLoading">
+    {{'common.alerts.nothingToDisplay' | translate: '{term: constants.users}'}}
+  </div>
+  <div class="col-sm-12 table-bar" ng-show="totalUsers > minRowsToShowPagination">
+    <div class="pull-left filtered-info">
+      <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.users}'}}</span>
+      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
+    </div>
+    <div class="pull-right left-margin">
+      <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
+    </div>
+    <div class="pull-right">
+      <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html
deleted file mode 100644
index 80a3b04..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/create.html
+++ /dev/null
@@ -1,82 +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.
--->
-<ol class="breadcrumb">
-  <li><a href="#/users">{{'common.users' | translate}}</a></li>
-  <li class="active">{{'users.create' | translate}}</li>
-</ol>
-<hr>
-<form class="form-horizontal create-user-form" role="form" novalidate name="form" autocomplete="off">
-  <div class="form-group" ng-class="{'has-error' : form.user_name.$error.required && form.submitted}">
-    <label for="username" class="col-sm-2 control-label">{{'users.username' | translate}}</label>
-    <div class="col-sm-10"
-         ng-class="{'has-error': form.user_name.$error.pattern}">
-      <input
-        autofocus
-        type="text"
-        id="username"
-        class="form-control username-input"
-        name="user_name"
-        placeholder="{{'users.userName' | translate}}"
-        ng-model="user.user_name"
-        ng-required="true"
-        ng-pattern="/^[^<>&`|\\]+$/"
-        ng-maxlength="80"
-        tooltip="{{'users.userNameTip' | translate}}"
-        autocomplete="off"
-        tooltip-trigger="focus">
-      <div class="alert alert-danger top-margin" ng-show="form.user_name.$error.required && form.submitted">{{'common.alerts.fieldIsRequired' | translate}}</div>
-    </div>
-  </div>
-  <div class="form-group">
-    <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
-    <div class="col-sm-10">
-      <label for="" class="control-label">{{'common.local' | translate}}</label>
-    </div>
-  </div>
-  <div class="form-group">
-    <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
-    <div class="col-sm-10">
-      <toggle-switch model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus" data-off-color="danger"></toggle-switch>
-    </div>
-  </div>
-  <div class="form-group">
-    <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span>{{'users.ambariAdmin' | translate}}</label>
-    <div class="col-sm-10">
-      <toggle-switch ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus" data-off-color="danger"></toggle-switch>
-    </div>
-    </div>
-  <div class="form-group" ng-class="{'has-error' : (form.password.$error.required && form.submitted) || form.confirmPassword.$error.passwordVerify}">
-    <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
-    <div class="col-sm-10">
-      <input type="password" class="form-control bottom-margin userpassword" name="password" placeholder="{{'users.password' | translate}}" required ng-model="user.password" autocomplete="off">
-      <input type="password" class="form-control bottom-margin userpasswordconfirm" name="confirmPassword" placeholder="{{'users.passwordConfirmation' | translate}}" required ng-model="user.passwordConfirmation"
-        password-verify="user.password" autocomplete="off">
-
-      <div class="alert alert-danger" ng-show='form.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
-      <div class="alert alert-danger" ng-show='form.password.$error.required && form.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
-      
-    </div>
-  </div>
-  <div class="form-group">
-    <div class="col-sm-offset-2 col-sm-10">
-      <button class="btn btn-primary pull-right left-margin saveuser" ng-click="createUser()">{{'common.controls.save' | translate}}</button>
-      <a class="btn btn-default pull-right cancel" href ng-click="cancel()">{{'common.controls.cancel' | translate}}</a>
-    </div>
-  </div>
-      
-</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
deleted file mode 100644
index 12227c3..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/list.html
+++ /dev/null
@@ -1,97 +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.
--->
-
-<div class="users-pane">
-  <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li class="active">{{'common.users' | translate}}</li>
-    </ol>
-    <div class="pull-right top-margin-4">
-      <link-to route="users.create" class="btn btn-default createuser-btn">
-        </span> {{'users.create' | translate}}
-      </link-to>
-    </div>
-  </div>
-  <table class="table table-striped table-hover">
-    <thead>
-      <tr>
-        <th width="30">
-          <span class="bottom-margin admin-filter glyphicon glyphicon-flash" 
-            ng-class="{'no-filter' : !adminFilter}" 
-            ng-click="toggleAdminFilter()"
-            tooltip="{{(adminFilter ? 'users.showAll' : 'users.showAdmin') | translate}}"
-          ></span>
-        </th>
-        <th>
-          <div class="search-container">
-            <label for="">{{'users.username' | translate}}</label>
-            <input type="text" class="form-control namefilter" placeholder="{{'common.any' | translate}}" ng-model="currentNameFilter" ng-change="resetPagination()">
-            <button type="button" class="close clearfilter" ng-show="currentNameFilter" ng-click="currentNameFilter=''; resetPagination()"><span aria-hidden="true">&times;</span><span class="sr-only">{{'common.controls.close' | translate}}</span></button>
-          </div>
-        </th>
-        <th>
-          <label for="">{{'common.type' | translate}}</label>
-          <select class="form-control typefilter"
-            ng-model="currentTypeFilter"
-            ng-options="item.label for item in typeFilterOptions"
-            ng-change="resetPagination()">
-          </select>
-
-        </th>
-        <th>
-          <label for="">{{'users.status' | translate}}</label>
-          <select class="form-control statusfilter" 
-            ng-model="currentActiveFilter"
-            ng-options="item.label for item in activeFilterOptions"
-            ng-change="resetPagination()">
-          </select>
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr ng-repeat="user in users">
-        <td>
-          <span class="glyphicon" tooltip="{{user.Users.admin ? constants.admin : ''}}" ng-class="{'glyphicon-flash' : user.Users.admin}"></span>
-        </td>
-        <td>
-           <a href="#/users/{{user.Users.encoded_name}}">{{user.Users.user_name}}</a>
-        </td>
-        <td>{{user.Users.userTypeName}}</td>
-        <td><span ng-class="user.Users.active ? 'text-success' : 'text-danger'">{{(user.Users.active ? 'users.active' : 'users.inactive') | translate}}</span></td>
-      </tr>
-    </tbody>
-  </table>
-  <div ng-if="isLoading" class="spinner-container">
-    <i class="fa fa-2x fa-spinner fa-spin" aria-hidden="true"></i>
-  </div>
-  <div class="alert empty-table-alert col-sm-12" ng-show="!users.length && !isLoading">
-    {{'common.alerts.nothingToDisplay' | translate: '{term: constants.users}'}}
-  </div>
-  <div class="col-sm-12 table-bar">
-    <div class="pull-left filtered-info">
-      <span>{{'common.filterInfo' | translate: '{showed: tableInfo.showed, total: tableInfo.total, term: constants.users}'}}</span>
-      <span ng-show="isNotEmptyFilter">- <a href ng-click="clearFilters()">{{'common.controls.clearFilters' | translate}}</a></span>
-    </div>
-    <div class="pull-right left-margin">
-      <pagination class="paginator" total-items="totalUsers" max-size="maxVisiblePages" items-per-page="usersPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
-    </div>
-    <div class="pull-right">
-      <select class="form-control" ng-model="usersPerPage" ng-change="usersPerPageChanges()" ng-options="currOption for currOption in [10, 25, 50, 100]"></select>
-    </div>
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html
deleted file mode 100644
index f29d315..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/modals/changePassword.html
+++ /dev/null
@@ -1,46 +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.
--->
-<div class="modal-header">
-  <h3 class="modal-title">{{'users.changePasswordFor' | translate: '{userName: userName}'}}</h3>
-</div>
-<div class="modal-body">
-  <form class="form-horizontal" novalidate name="form.passwordChangeForm" role="form" >
-    <div class="form-group" ng-class="{'has-error' : (form.passwordChangeForm.currentPassword.$error.required && form.passwordChangeForm.submitted)}">
-      <label for="" class="col-sm-4 control-label" >{{'users.yourPassword' | translate}}</label>
-      <div class="col-sm-8">
-        <input type="password" name="currentPassword" class="form-control bottom-margin" placeholder="{{'users.yourPassword' | translate}}" required ng-model="passwordData.currentUserPassword" autocomplete="off">
-        <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
-      </div>
-    </div>
-    <div class="form-group no-margin-bottom" ng-class="{'has-error' : (form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted) || form.passwordChangeForm.confirmPassword.$error.passwordVerify}">
-      <label for="" class="col-sm-4 control-label">{{'users.newPassword' | translate}}:</label>
-      <div class="col-sm-8">
-        <input type="password" class="form-control bottom-margin" name="password" placeholder="{{'users.newPassword' | translate}}" required ng-model="passwordData.password" autocomplete="off">
-        <input type="password" class="form-control bottom-margin" name="confirmPassword" placeholder="{{'users.newPasswordConfirmation' | translate}}" required ng-model="passwordData.passwordConfirmation"
-          password-verify="passwordData.password" autocomplete="off">
-        <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.confirmPassword.$error.passwordVerify'>{{'users.alerts.wrongPassword' | translate}}</div>
-        <div class="alert alert-danger no-margin-bottom" ng-show='form.passwordChangeForm.password.$error.required && form.passwordChangeForm.submitted'>{{'users.alerts.passwordRequired' | translate}}</div>
-      </div>
-
-    </div>
-  </form>
-</div>
-<div class="modal-footer">
-  <button class="btn btn-default" ng-click="cancel()">{{'common.controls.cancel' | translate}}</button>
-  <button class="btn btn-primary" ng-click="ok()">{{'common.controls.ok' | translate}}</button>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
deleted file mode 100644
index f965c5d..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/views/users/show.html
+++ /dev/null
@@ -1,122 +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.
--->
-    
-<div ng-show="user" class="user-edit-panel">
-  <div class="clearfix">
-    <ol class="breadcrumb pull-left">
-      <li><a href="#/users">{{'common.users' | translate}}</a></li>
-      <li class="active"><span class="glyphicon glyphicon-flash" ng-show="user.admin"></span>{{user.user_name}}</li>
-    </ol>
-    <div class="pull-right top-margin-4">
-      <div ng-switch="isCurrentUser || user.user_type != 'LOCAL'">
-        <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'common.cannotDelete' | translate: '{term: constants.user}'}}">{{'common.delete' | translate: '{term: constants.user}'}}</button>
-        <button class="btn deleteuser-btn btn-danger" ng-switch-when="false" ng-click="deleteUser()">{{'common.delete' | translate: '{term: constants.user}'}}</button>
-      </div>
-    </div>
-  </div>
-  <hr>
-  <form class="form-horizontal" role="form" >
-    <div class="form-group">
-      <label for="" class="col-sm-2 control-label">{{'common.type' | translate}}</label>
-      <div class="col-sm-10">
-        <label for="" class="control-label">{{user.userTypeName}}</label>
-      </div>
-    </div>
-    <div class="form-group">
-      <label for="" class="col-sm-2 control-label">{{'users.status' | translate}}</label>
-      <div class="col-sm-10">
-        <toggle-switch on-change="toggleUserActive()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.status}'}}" ng-disabled="isCurrentUser" model="user.active" on-label="{{'users.active' | translate}}" off-label="{{'users.inactive' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
-      </div>
-    </div>
-    <div class="form-group">
-      <label for="" class="col-sm-2 control-label"><span class="glyphicon glyphicon-flash"></span> {{'users.ambariAdmin' | translate}}</label>
-      <div class="col-sm-10">
-        <toggle-switch on-change="toggleUserAdmin()" disabled-tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.admin}'}}" ng-disabled="isCurrentUser" model="user.admin" on-label="{{'common.yes' | translate}}" off-label="{{'common.no' | translate}}" class="switch-primary userstatus {{user ? '' : 'no-animation'}}" data-off-color="danger"></toggle-switch>
-      </div>
-    </div>
-    <div class="form-group">
-      <label for="password" class="col-sm-2 control-label">{{'users.password' | translate}}</label>
-      <div class="col-sm-10">
-        <div ng-switch="user.user_type != 'LOCAL'">
-          <button class="btn deleteuser-btn disabled btn-default" ng-switch-when="true" tooltip="{{'users.alerts.cannotChange' | translate: '{term: constants.password}'}}">{{'users.changePassword' | translate}}</button>
-          <a href ng-click="openChangePwdDialog()" ng-switch-when="false" class="btn btn-default changepassword">{{'users.changePassword' | translate}}</a>
-        </div>
-          
-      </div>
-    </div>
-    <div class="form-group">
-      <label for="groups" class="col-sm-2 control-label">{{getUserMembership(user.user_type)}}</label>
-      <div class="col-sm-10">
-        <editable-list items-source="editingGroupsList" resource-type="Group" editable="user.user_type == 'LOCAL'"></editable-list>
-      </div>
-        
-    </div>
-    <div class="form-group" >
-      <label for="" class="col-sm-2 control-label">{{'common.privileges' | translate}}</label>
-      <div class="col-sm-10">
-        <table class="table" ng-hide="hidePrivileges || user.admin">
-          <thead>
-            <tr>
-              <th>{{'common.cluster' | translate}}</th>
-              <th>{{'common.clusterRole' | translate}}</th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.clusters">
-              <td>
-                <span class="glyphicon glyphicon-cloud"></span> 
-                <a href="#/clusters/{{name}}/manageAccess">{{name}}</a>
-              </td>
-              <td>
-                <span tooltip="{{privilege.permission_label}}">{{privilege.permission_label}}</span>
-              </td>
-            </tr>
-            <tr>
-              <td ng-show="noClusterPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.cluster}'}}</td>
-            </tr>
-          </tbody>
-          <thead class="view-permission-header">
-            <tr>
-              <th>{{'common.view' | translate}}</th>
-              <th>{{'common.viewPermissions' | translate}}</th>
-            </tr>
-          </thead>
-          <tbody>
-            <tr ng-repeat="(name, privilege) in privileges.views">
-              <td>
-                <span class="glyphicon glyphicon-th"></span>
-                <a href="#/views/{{privilege.view_name}}/versions/{{privilege.version}}/instances/{{name}}/edit">{{name}}</a>
-              </td>
-              <td>
-                <span tooltip="{{item}}" ng-repeat="item in privilege.privileges track by $index">{{item | translate}}{{$last ? '' : ', '}}</span>
-              </td>
-              <td>
-                <i class="fa fa-trash-o" aria-hidden="true" ng-click="removePrivilege(name, privilege);"></i>
-              </td>
-            </tr>
-            <tr>
-              <td ng-show="noViewPriv">{{'common.alerts.noPrivileges' | translate: '{term: constants.view}'}}</td>
-            </tr>
-          </tbody>
-        </table>
-        <div class="alert alert-info" ng-show="!privileges && !user.admin">{{'common.alerts.noPrivilegesDescription' | translate: '{term: constants.user}'}}</div>
-        <div class="alert alert-info" ng-show="user.admin">{{'users.userIsAdmin' | translate}}</div>
-      </div>
-    </div>
-  </form>
-</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
deleted file mode 100644
index 14c0975..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
+++ /dev/null
@@ -1,820 +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.
- */
-
-describe('#Cluster', function () {
-
-  describe('UserAccessListCtrl', function() {
-
-    var scope, ctrl, $t, $httpBackend, Cluster, deferred, Alert, mock;
-
-    beforeEach(module('ambariAdminConsole', function () {}));
-
-    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_, _Cluster_, _$q_, _Alert_) {
-      scope = $rootScope.$new();
-      $t = _$translate_.instant;
-      $httpBackend = _$httpBackend_;
-      Cluster = _Cluster_;
-      Alert = _Alert_;
-      deferred = {
-        createPrivileges: _$q_.defer(),
-        getPrivilegesForResource: _$q_.defer(),
-        getPrivilegesWithFilters: _$q_.defer(),
-        deletePrivileges: _$q_.defer(),
-        deleteMultiplePrivileges: _$q_.defer()
-      };
-      ctrl = $controller('UserAccessListCtrl', {
-        $scope: scope
-      });
-      mock = {
-        Cluster: Cluster,
-        Alert: Alert,
-        scope: scope
-      };
-      spyOn(Cluster, 'createPrivileges').andReturn(deferred.createPrivileges.promise);
-      spyOn(Cluster, 'deletePrivileges').andReturn(deferred.deletePrivileges.promise);
-      spyOn(Cluster, 'getPrivilegesForResource').andReturn(deferred.getPrivilegesForResource.promise);
-      spyOn(Cluster, 'getPrivilegesWithFilters').andReturn(deferred.getPrivilegesWithFilters.promise);
-      spyOn(Alert, 'success').andCallFake(angular.noop);
-      spyOn(Alert, 'error').andCallFake(angular.noop);
-      spyOn(scope, 'loadRoles').andCallFake(angular.noop);
-
-      $httpBackend.expectGET(/\/api\/v1\/permissions/).respond(200, {
-        items: []
-      });
-      $httpBackend.expectGET(/\/api\/v1\/users?.*/).respond(200, {
-        items:[]
-      });
-      $httpBackend.flush();
-    }));
-
-    describe('#clearFilters()', function () {
-
-      it('should clear filters and reset pagination', function () {
-        scope.currentPage = 2;
-        scope.currentNameFilter = 'a';
-        scope.roleFilterOptions = [
-          {
-            label: $t('common.all'),
-            value: ''
-          },
-          {
-            label: $t('users.roles.clusterUser'),
-            value: 'CLUSTER.USER'
-          }
-        ];
-        scope.currentRoleFilter = scope.roleFilterOptions[1];
-        scope.clearFilters();
-        expect(scope.currentNameFilter).toEqual('');
-        expect(scope.currentRoleFilter).toEqual({
-          label: $t('common.all'),
-          value: ''
-        });
-        expect(scope.currentPage).toEqual(1);
-      });
-
-    });
-
-    describe('#isNotEmptyFilter', function () {
-
-      var cases = [
-        {
-          currentNameFilter: '',
-          currentRoleFilter: null,
-          isNotEmptyFilter: false,
-          title: 'no filters'
-        },
-        {
-          currentNameFilter: '',
-          currentRoleFilter: {
-            value: ''
-          },
-          isNotEmptyFilter: false,
-          title: 'empty filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentRoleFilter: {
-            value: ''
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter'
-        },
-        {
-          currentNameFilter: '0',
-          currentRoleFilter: {
-            value: ''
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentRoleFilter: {
-            value: 'CLUSTER.USER'
-          },
-          isNotEmptyFilter: true,
-          title: 'role filter'
-        },
-        {
-          currentNameFilter: 'a',
-          currentRoleFilter: {
-            value: 'GROUP'
-          },
-          isNotEmptyFilter: true,
-          title: 'all filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentRoleFilter: {
-            value: 'GROUP'
-          },
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string'
-        }
-      ];
-
-      cases.forEach(function (item) {
-        it(item.title, function () {
-          scope.currentNameFilter = item.currentNameFilter;
-          scope.currentRoleFilter = item.currentRoleFilter;
-          scope.$digest();
-          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
-        });
-      });
-
-    });
-
-    describe('#save() for Users', function(){
-      var user = {};
-
-      beforeEach(function() {
-        items1 = {
-            "href" : "http://abc.com:8080/api/v1/users/user1",
-            "Users" : { "user_name" : "user1" },
-            "privileges" : [
-              {
-                "href" : "http://abc.com:8080/api/v1/users/user1/privileges/222",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "mygroup2",
-                  "principal_type" : "GROUP",
-                  "privilege_id" : 222,
-                  "type" : "CLUSTER",
-                  "user_name" : "user1"
-                }
-              }, {
-                "href" : "http://abc.com:8080/api/v1/users/user1/privileges/111",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "mygroup",
-                  "principal_type" : "GROUP",
-                  "privilege_id" : 111,
-                  "type" : "CLUSTER",
-                  "user_name" : "user1"
-                }
-              }, {
-                "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Cluster Administrator",
-                  "permission_name" : "CLUSTER.ADMINISTRATOR",
-                  "principal_name" : "user1",
-                  "principal_type" : "USER",
-                  "privilege_id" : 11,
-                  "type" : "CLUSTER",
-                  "user_name" : "user1"
-                }
-              }
-            ]
-          };
-
-        items2 =
-          {
-            "href" : "http://abc.com:8080/api/v1/users/user2",
-            "Users" : { "user_name" : "user2" },
-            "privileges" : [
-              {
-                "href" : "http://abc.com:8080/api/v1/users/user2/privileges/111",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "mygroup",
-                  "principal_type" : "GROUP",
-                  "privilege_id" : 111,
-                  "type" : "CLUSTER",
-                  "user_name" : "user2"
-                }
-              }, {
-                "href" : "http://abc.com:8080/api/v1/users/user2/privileges/22",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "user2",
-                  "principal_type" : "USER",
-                  "privilege_id" : 22,
-                  "type" : "CLUSTER",
-                  "user_name" : "user2"
-                }
-              }
-            ]
-          };
-
-        all_items = { "items": [items1, items2]};
-
-        scope.loadUsers();
-
-        spyOn(Cluster, 'deleteMultiplePrivileges').andCallFake(function(clusterId, privilege_ids) {
-          privilege_ids.forEach(function(privilege_id) {
-            items1.privileges.forEach(function(p, index) {
-              if (p.PrivilegeInfo.privilege_id === privilege_id) {
-                //Remove from array
-                items1.privileges.splice(index, 1);
-              }
-            });
-          });
-        });
-        spyOn(scope, 'addPrivilege').andCallFake(function(user) {
-          var p = {};
-          p.PrivilegeInfo = {};
-          p.PrivilegeInfo.privilege_id = user.privilege_id + 1;
-          p.PrivilegeInfo.permission_name = user.permission_name;
-          p.PrivilegeInfo.principal_type = 'USER';
-
-          items1.privileges.push(p);
-          scope.loadUsers();
-        });
-
-        deferred.getPrivilegesWithFilters.resolve(all_items);
-        deferred.getPrivilegesForResource.promise.then(function(data) {
-          var arrayOfPrivileges = data.items[0].privileges;
-          var privilegesOfTypeUser = [];
-          var privilegesOfTypeGroup = [];
-          for (var i = 0; i < arrayOfPrivileges.length; i++) {
-            if(arrayOfPrivileges[i].PrivilegeInfo.principal_type === "GROUP"){
-              privilegesOfTypeGroup.push(arrayOfPrivileges[i]);
-            } else {
-              privilegesOfTypeUser.push(arrayOfPrivileges[i].PrivilegeInfo);
-            }
-          }
-
-          var effectivePrivilege = scope.pickEffectivePrivilege(arrayOfPrivileges);
-          var effectivePrivilegeFromGroups = scope.pickEffectivePrivilege(privilegesOfTypeGroup);
-          user.principal_type = 'USER';
-          user.original_perm = effectivePrivilege.permission_name;
-          user.editable = (Cluster.ineditableRoles.indexOf(effectivePrivilege.permission_name) === -1);
-
-          //add a new privilege of type USER only if it is also the effective privilege considering the user's Group privileges
-          var curIndex = scope.getRoleRank(user.permission_name);
-          var prevIndex = -1;
-          if (privilegesOfTypeGroup.length !== 0) {
-            prevIndex = scope.getRoleRank(effectivePrivilegeFromGroups.permission_name);
-          }
-          if ((curIndex === 6) || (curIndex <= prevIndex)) {
-            var privilege_ids = [];
-            privilegesOfTypeUser.forEach(function(privilegeOfTypeUser) {
-              privilege_ids.push(privilegeOfTypeUser.privilege_id);
-            });
-
-            //delete all privileges of type USER, if they exist
-            //then add the privilege for the user, after which the user displays the effective privilege
-            if(privilege_ids.length !== 0) {
-              Cluster.deleteMultiplePrivileges(
-                123,
-                privilege_ids
-              );
-            }
-            scope.addPrivilege(user);
-          } else {
-            Alert.error($t('common.alerts.cannotSavePermissions'), "User's effective privilege through its Group(s) is higher than your selected privilege.");
-            scope.loadUsers();
-          }
-        });
-
-        scope.$apply();
-      });
-
-      it('Should save the Privilege equal to the user\'s group privileges. Should also remove any individual user privileges', function() {
-        //using 'user1' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "SERVICE.ADMINISTRATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "permission_label" : "Cluster Administrator",
-            "permission_name" : "CLUSTER.ADMINISTRATOR",
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : 11,
-            "type" : "CLUSTER",
-            "user_name" : "user1"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "permission_name" : user.permission_name,
-            "privilege_id" : user.privilege_id+1,
-            "principal_type" : "USER",
-            "principal_name" : "user1",
-            "encoded_name" : "user1",
-            "original_perm" : user.permission_name,
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-
-        //test if the individual user privilege CLUSTER.ADMINISTRATOR is removed from 'items1' by deletePrivilege()
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege got added to 'items1' by addPrivilege()
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should save the Privilege greater than the user\'s group privileges. Should also remove any individual user privileges', function() {
-        //using 'user1' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.OPERATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "permission_label" : "Cluster Administrator",
-            "permission_name" : "CLUSTER.ADMINISTRATOR",
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : 11,
-            "type" : "CLUSTER",
-            "user_name" : "user1"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "permission_name" : user.permission_name,
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : user.privilege_id + 1,
-            "encoded_name" : "user1",
-            "original_perm" : user.permission_name,
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-
-        //test if the individual user privilege CLUSTER.ADMINISTRATOR is removed from 'items1' by deletePrivilege()
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege got added to 'items1' by addPrivilege()
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should NOT save the Privilege smaller than the user\'s group privileges. Should keep the user\'s original privileges intact', function() {
-        //using 'user1' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.USER";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.original_perm);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id);
-
-        var oldPrivilege = {
-          "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "permission_label" : "Cluster Administrator",
-            "permission_name" : "CLUSTER.ADMINISTRATOR",
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : 11,
-            "type" : "CLUSTER",
-            "user_name" : "user1",
-            "encoded_name" : "user1",
-            "original_perm" : "CLUSTER.ADMINISTRATOR",
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "permission_name" : user.permission_name,
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : user.privilege_id+1,
-            "encoded_name" : "user1",
-            "original_perm" : user.permission_name,
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-
-        //test if the individual user privilege CLUSTER.ADMINISTRATOR is NOT removed from 'items1'
-        expect(items1.privileges).toContain(oldPrivilege);
-
-        //test if the new privilege is NOT added to 'items1'
-        expect(items1.privileges).toNotContain(newPrivilege);
-      });
-
-    });
-
-    describe('#save() for Groups', function() {
-      var user = {};
-
-      beforeEach(function() {
-        items1 = {
-          "href" : "http://abc.com:8080/api/v1/groups/mygroup",
-          "Groups" : { "group_name" : "mygroup" },
-          "privileges" : [
-            {
-              "href" : "http://abc.com:8080/api/v1/groups/mygroup/privileges/3359",
-              "PrivilegeInfo" : {
-                "cluster_name" : "myCluster",
-                "group_name" : "mygroup",
-                "permission_label" : "Service Administrator",
-                "permission_name" : "SERVICE.ADMINISTRATOR",
-                "principal_name" : "mygroup",
-                "principal_type" : "GROUP",
-                "privilege_id" : 3359,
-                "type" : "CLUSTER"
-              }
-            }
-          ]
-        };
-
-        items2 = {
-          "href" : "http://abc.com:8080/api/v1/groups/mygroup2",
-          "Groups" : { "group_name" : "mygroup2" },
-          "privileges" : [
-            {
-              "href" : "http://abc.com:8080/api/v1/groups/mygroup2/privileges/3356",
-              "PrivilegeInfo" : {
-                "cluster_name" : "myCluster",
-                "group_name" : "mygroup2",
-                "permission_label" : "Service Administrator",
-                "permission_name" : "SERVICE.ADMINISTRATOR",
-                "principal_name" : "mygroup2",
-                "principal_type" : "GROUP",
-                "privilege_id" : 3356,
-                "type" : "CLUSTER"
-              }
-            }
-          ]
-        };
-
-        all_items = { "items": [items1, items2]};
-
-        scope.loadUsers();
-
-        spyOn(Cluster, 'deleteMultiplePrivileges').andCallFake(function(clusterId, privilege_ids) {
-          privilege_ids.forEach(function(privilege_id) {
-            items1.privileges.forEach(function(p, index) {
-              if (p.PrivilegeInfo.privilege_id === privilege_id) {
-                //Remove from array
-                items1.privileges.splice(index, 1);
-              }
-            });
-          });
-        });
-        spyOn(scope, 'addPrivilege').andCallFake(function(user) {
-          var p = {};
-          p.PrivilegeInfo = {};
-          p.PrivilegeInfo.privilege_id = user.privilege_id + 1;
-          p.PrivilegeInfo.permission_name = user.permission_name;
-          p.PrivilegeInfo.principal_type = 'GROUP';
-
-          items1.privileges.push(p);
-          scope.loadUsers();
-        });
-
-        deferred.getPrivilegesWithFilters.resolve(all_items);
-        deferred.getPrivilegesForResource.promise.then(function(data) {
-          var arrayOfPrivileges = data.items[0].privileges;
-          var privilegesOfTypeGroup = [];
-          var privilege = scope.pickEffectivePrivilege(arrayOfPrivileges);
-          user.principal_type = 'GROUP';
-          user.original_perm = privilege.permission_name;
-          user.editable = (Cluster.ineditableRoles.indexOf(privilege.permission_name) === -1);
-
-          arrayOfPrivileges.forEach(function(privilegeOfTypeGroup){
-            if (privilegeOfTypeGroup.PrivilegeInfo.principal_type === "GROUP") {
-              privilegesOfTypeGroup.push(privilegeOfTypeGroup.PrivilegeInfo);
-            }
-          });
-
-          var privilege_ids = [];
-          privilegesOfTypeGroup.forEach(function(privilegeOfTypeGroup) {
-            privilege_ids.push(privilegeOfTypeGroup.privilege_id);
-          });
-
-          //delete all privileges of type GROUP, if they exist
-          //then add the privilege for the group, after which the group displays the effective privilege
-          if(privilege_ids.length !== 0) {
-            Cluster.deleteMultiplePrivileges(
-                123,
-                privilege_ids
-            );
-          }
-          scope.addPrivilege(user);
-        });
-
-        scope.$apply();
-      });
-
-      it('Should save the Privilege equal to the group\'s effective privilege. Should remove any other privileges of the group',function(){
-        //using 'mygroup' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "SERVICE.ADMINISTRATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "group_name" : "mygroup",
-            "permission_label" : "Service Administrator",
-            "permission_name" : "SERVICE.ADMINISTRATOR",
-            "principal_name" : "mygroup",
-            "principal_type" : "GROUP",
-            "privilege_id" : 3359,
-            "type" : "CLUSTER"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "privilege_id" : user.privilege_id + 1,
-            "permission_name" : user.permission_name,
-            "principal_type" : "GROUP",
-            "principal_name" : "mygroup",
-            "encoded_name" : "mygroup",
-            "original_perm" : user.permission_name,
-            "url" : "groups/mygroup/edit",
-            "editable" : true
-          }
-        };
-
-        //test if the older privilege is no longer present in 'items1'
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege is added to 'items1'
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should save the Privilege greater than the group\'s effective privilege. Should remove any other privileges of the group',function(){
-        //using 'mygroup' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.ADMINISTRATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "group_name" : "mygroup",
-            "permission_label" : "Service Administrator",
-            "permission_name" : "SERVICE.ADMINISTRATOR",
-            "principal_name" : "mygroup",
-            "principal_type" : "GROUP",
-            "privilege_id" : 3359,
-            "type" : "CLUSTER"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "privilege_id" : user.privilege_id + 1,
-            "permission_name" : user.permission_name,
-            "principal_type" : "GROUP",
-            "principal_name" : "mygroup",
-            "encoded_name" : "mygroup",
-            "original_perm" : user.permission_name,
-            "url" : "groups/mygroup/edit",
-            "editable" : true
-          }
-        };
-
-        //test if the older privilege is no longer present in 'items1'
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege is added to 'items1'
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should save the Privilege lesser than the group\'s effective privilege. Should remove any other privileges of the group', function() {
-        //using 'mygroup' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.USER";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "group_name" : "mygroup",
-            "permission_label" : "Service Administrator",
-            "permission_name" : "SERVICE.ADMINISTRATOR",
-            "principal_name" : "mygroup",
-            "principal_type" : "GROUP",
-            "privilege_id" : 3359,
-            "type" : "CLUSTER"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "privilege_id" : user.privilege_id + 1,
-            "permission_name" : user.permission_name,
-            "principal_type" : "GROUP",
-            "principal_name" : "mygroup",
-            "encoded_name" : "mygroup",
-            "original_perm" : user.permission_name,
-            "url" : "groups/mygroup/edit",
-            "editable" : true
-          }
-        };
-
-        //test if the older privilege is no longer present in 'items1'
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege is added to 'items1'
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-    });
-
-    describe('#pickEffectivePrivilege()', function() {
-      var cases = [{
-          "test" : [{
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup1",
-            "PrivilegeInfo" : {
-              "instance_name" : "jobs_view",
-              "permission_label" : "View User",
-              "permission_name" : "VIEW.USER",
-              "principal_name" : "mygroup1",
-              "principal_type" : "GROUP",
-              "privilege_id" : 111,
-              "type" : "VIEW",
-              "user_name" : "mygroup1",
-              "view_name" : "JOBS"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.NONE"
-          }
-        }, {
-          "test": [{
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup2",
-            "PrivilegeInfo" : {
-              "cluster_name":"mycluster",
-              "permission_label" : "Cluster User",
-              "permission_name" : "CLUSTER.USER",
-              "principal_name" : "mygroup2",
-              "principal_type" : "GROUP",
-              "privilege_id" : 222,
-              "type" : "CLUSTER",
-              "user_name":"mygroup2"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.USER"
-          }
-        }, {
-          "test":[{
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup3",
-            "PrivilegeInfo" : {
-              "cluster_name":"mycluster",
-              "permission_label" : "Cluster User",
-              "permission_name" : "CLUSTER.USER",
-              "principal_name" : "mygroup3",
-              "principal_type" : "GROUP",
-              "privilege_id" : 333,
-              "type" : "CLUSTER",
-              "user_name":"mygroup3"
-            }
-          }, {
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup3",
-            "PrivilegeInfo" : {
-              "instance_name": "jobs_view",
-              "permission_label" : "View User",
-              "permission_name" : "VIEW.USER",
-              "principal_name" : "mygroup3",
-              "principal_type" : "GROUP",
-              "privilege_id" : 3333,
-              "type" : "VIEW",
-              "user_name":"mygroup3",
-              "view_name":"JOBS"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.USER"
-          }
-        }, {
-          "test": [{
-            "href" : "http://abc.com:8080/api/v1/users/myuser1/privileges/11",
-            "PrivilegeInfo" : {
-              "instance_name": "jobs_view",
-              "permission_label" : "View User",
-              "permission_name" : "VIEW.USER",
-              "principal_name" : "myuser1",
-              "principal_type" : "USER",
-              "privilege_id" : 11,
-              "type" : "VIEW",
-              "user_name":"myuser1",
-              "view_name":"JOBS"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.NONE"
-          }
-        }, {
-          "test":[{
-            "href" : "http://abc.com:8080/api/v1/users/myuser2/privileges/22",
-            "PrivilegeInfo" : {
-              "cluster_name":"mycluster",
-              "permission_label" : "Cluster Administrator",
-              "permission_name" : "CLUSTER.ADMINISTRATOR",
-              "principal_name" : "myuser2",
-              "principal_type" : "USER",
-              "privilege_id" : 22,
-              "type" : "CLUSTER",
-              "user_name":"myuser2"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.ADMINISTRATOR"
-          }
-        }
-      ];
-
-      it('User/Group with only View User permission must show \'None\' as the Cluster Permission, otherwise show the effective privilege', function(){
-        var effectivePrivilege;
-        cases.forEach(function (item){
-          effectivePrivilege = scope.pickEffectivePrivilege(item.test);
-          scope.$apply();
-          expect(effectivePrivilege.permission_name).toEqual(item.result.permission_name);
-        });
-      });
-    });
-
-  });
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
deleted file mode 100644
index 8ed228b..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
+++ /dev/null
@@ -1,129 +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.
- */
-
-describe('#Cluster', function () {
-
-  describe('GroupsListCtrl', function() {
-
-    var scope, ctrl, $t, $httpBackend;
-
-    beforeEach(module('ambariAdminConsole', function () {}));
-
-    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
-      scope = $rootScope.$new();
-      $t = _$translate_.instant;
-      $httpBackend = _$httpBackend_;
-      ctrl = $controller('GroupsListCtrl', {
-        $scope: scope
-      });
-    }));
-
-    describe('#clearFilters()', function () {
-
-      it('should clear filters and reset pagination', function () {
-        scope.currentPage = 2;
-        scope.currentNameFilter = 'a';
-        scope.currentTypeFilter = {
-          label: $t('common.local'),
-          value: false
-        };
-        scope.clearFilters();
-        expect(scope.currentNameFilter).toEqual('');
-        expect(scope.currentTypeFilter).toEqual({
-          label: $t('common.all'),
-          value: '*'
-        });
-        expect(scope.currentPage).toEqual(1);
-      });
-
-    });
-
-    describe('#isNotEmptyFilter', function () {
-
-      var cases = [
-        {
-          currentNameFilter: '',
-          currentTypeFilter: null,
-          isNotEmptyFilter: false,
-          title: 'no filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          isNotEmptyFilter: false,
-          title: 'empty filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: false
-          },
-          isNotEmptyFilter: true,
-          title: 'type filter'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: false
-          },
-          isNotEmptyFilter: true,
-          title: 'both filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: false
-          },
-          isNotEmptyFilter: true,
-          title: 'both filters with "0" as string'
-        }
-      ];
-
-      cases.forEach(function (item) {
-        it(item.title, function () {
-          $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
-          scope.currentNameFilter = item.currentNameFilter;
-          scope.currentTypeFilter = item.currentTypeFilter;
-          scope.$digest();
-          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
-        });
-      });
-
-    });
-
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
new file mode 100644
index 0000000..8d04757
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
@@ -0,0 +1,129 @@
+/**
+ * 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.
+ */
+
+describe('#Cluster', function () {
+
+  describe('GroupsListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('GroupsListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.filter.name = 'a';
+        scope.filter.type = {
+          label: $t('common.local'),
+          value: false
+        };
+        scope.clearFilters();
+        expect(scope.filter.name).toEqual('');
+        expect(scope.filter.type).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
+          scope.filter.name = item.currentNameFilter;
+          scope.filter.type = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});


[21/50] [abbrv] ambari git commit: AMBARI-22514. Initial implementation of Schedulable document deletion & archiving for Infra Solr (Krisztian Kasa via oleewere)

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/SolrQueryBuilderTest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/SolrQueryBuilderTest.java b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/SolrQueryBuilderTest.java
new file mode 100644
index 0000000..4d5ebf1
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/SolrQueryBuilderTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+package org.apache.ambari.infra.job.archive;
+
+import org.apache.solr.client.solrj.SolrQuery;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+
+import static org.apache.ambari.infra.job.archive.SolrQueryBuilder.PARAMETER_PATTERN;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertThat;
+
+public class SolrQueryBuilderTest {
+  private static final Document DOCUMENT = new Document(new HashMap<String, String>() {{
+    put("logtime", "2017-10-02'T'10:00:11.634Z");
+    put("id", "1");
+  }});
+
+  @Test
+  public void testDefaultQuery() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder()
+            .build();
+    assertThat(solrQuery.getQuery(), is("*:*"));
+  }
+
+  @Test
+  public void testSetQuery() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder()
+            .setQueryText("logtime:[* TO \"${end}\"]")
+            .setEndValue("2017-11-27'T'10:12:11.372Z")
+            .build();
+    assertThat(solrQuery.getQuery(), is("logtime:[* TO \"2017-11-27'T'10:12:11.372Z\"]"));
+  }
+
+  @Test
+  public void testSetFilterQuery() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder()
+            .setFilterQueryText("(logtime:\"${logtime}\" AND id:{\"${id}\" TO *]) OR logtime:{\"${logtime}\" TO \"${end}\"]")
+            .setDocument(DOCUMENT)
+            .setEndValue("2017-11-27'T'10:12:11.372Z")
+            .build();
+    assertThat(solrQuery.getFilterQueries()[0], is("(logtime:\"2017-10-02'T'10:00:11.634Z\" AND id:{\"1\" TO *]) OR logtime:{\"2017-10-02'T'10:00:11.634Z\" TO \"2017-11-27'T'10:12:11.372Z\"]"));
+  }
+
+  @Test
+  public void testSetFilterQueryWhenDocumentIsNull() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder()
+            .setFilterQueryText("(logtime:\"${logtime}\" AND id:{\"${id}\" TO *]) OR logtime:{\"${logtime}\" TO \"${end}\"]")
+            .setEndValue("2017-11-27'T'10:12:11.372Z")
+            .build();
+    assertThat(solrQuery.getFilterQueries(), is(nullValue()));
+  }
+
+  @Test
+  public void testSetFilterQueryWhenEndValueIsNull() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder()
+            .setFilterQueryText("logtime:\"${logtime}\" AND id:{\"${id}\" TO *]")
+            .setDocument(DOCUMENT)
+            .build();
+    assertThat(solrQuery.getFilterQueries()[0], is("logtime:\"2017-10-02'T'10:00:11.634Z\" AND id:{\"1\" TO *]"));
+  }
+
+  @Test
+  public void testSetFilterQueryWhenQueryFilterIsNullButDocumentIsNot() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder()
+            .setDocument(DOCUMENT)
+            .build();
+    assertThat(solrQuery.getFilterQueries(), is(nullValue()));
+  }
+
+  @Test
+  public void testRegex() throws Exception {
+    Matcher matcher = PARAMETER_PATTERN.matcher("(logtime:\"${logtime}\" AND id:{\"${id}\" TO *]) OR logtime:{\"${logtime}\" TO \"${end}\"]");
+    List<String> parameters = new ArrayList<>();
+    while (matcher.find())
+      parameters.add(matcher.group());
+
+    assertThat(parameters, hasSize(4));
+    assertThat(parameters.get(0), is("${logtime}"));
+    assertThat(parameters.get(1), is("${id}"));
+    assertThat(parameters.get(2), is("${logtime}"));
+    assertThat(parameters.get(3), is("${end}"));
+  }
+
+  @Test
+  public void testSort() throws Exception {
+    SolrQuery solrQuery = new SolrQueryBuilder().addSort("logtime", "id").build();
+    assertThat(solrQuery.getSorts().get(0).getItem(), is("logtime"));
+    assertThat(solrQuery.getSorts().get(1).getItem(), is("id"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/393fdb80/ambari-logsearch/docker/test-config/logfeeder/logfeeder.properties
----------------------------------------------------------------------
diff --git a/ambari-logsearch/docker/test-config/logfeeder/logfeeder.properties b/ambari-logsearch/docker/test-config/logfeeder/logfeeder.properties
index fb7ddf2..1ae57bb 100644
--- a/ambari-logsearch/docker/test-config/logfeeder/logfeeder.properties
+++ b/ambari-logsearch/docker/test-config/logfeeder/logfeeder.properties
@@ -29,4 +29,4 @@ logfeeder.cache.key.field=log_message
 logfeeder.cache.dedup.interval=1000
 logfeeder.cache.last.dedup.enabled=true
 logsearch.config.zk_connect_string=localhost:9983
-logfeeder.include.default.level=FATAL,ERROR,WARN,INFO,DEBUG,TRACE,UNKNOWN
+logfeeder.include.default.level=FATAL,ERROR,WARN,INFO,DEBUG,TRACE,UNKNOWN
\ No newline at end of file


[49/50] [abbrv] ambari git commit: Merge branch 'trunk' into branch-3.0-perf

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 4f57881,455814a..6118229
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@@ -130,9 -107,8 +132,10 @@@ import org.apache.ambari.server.control
  import org.apache.ambari.server.controller.metrics.MetricsCollectorHAManager;
  import org.apache.ambari.server.controller.metrics.timeline.cache.TimelineMetricCacheProvider;
  import org.apache.ambari.server.controller.spi.Resource;
+ import org.apache.ambari.server.controller.spi.SystemException;
  import org.apache.ambari.server.customactions.ActionDefinition;
 +import org.apache.ambari.server.events.MetadataUpdateEvent;
 +import org.apache.ambari.server.events.TopologyUpdateEvent;
  import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
  import org.apache.ambari.server.metadata.ActionMetadata;
  import org.apache.ambari.server.metadata.RoleCommandOrder;
@@@ -353,26 -325,8 +358,29 @@@ public class AmbariManagementController
    protected OsFamily osFamily;
  
    @Inject
 +  private TopologyDeleteFormer topologyDeleteFormer;
 +
 +  @Inject
 +  private AmbariCustomCommandExecutionHelper ambariCustomCommandExecutionHelper;
 +
 +  @Inject
 +  private Provider<TopologyHolder> m_topologyHolder;
 +
 +  @Inject
 +  private Provider<MetadataHolder> m_metadataHolder;
 +
 +  @Inject
 +  private Provider<AgentConfigsHolder> m_agentConfigsHolder;
 +
 +  @Inject
 +  private Provider<HostLevelParamsHolder> m_hostLevelParamsHolder;
 +
 +  @Inject
 +  private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;
 +
++  @Inject
+   private RepositoryVersionHelper repoVersionHelper;
+ 
    /**
     * The KerberosHelper to help setup for enabling for disabling Kerberos
     */
@@@ -2595,7 -2469,12 +2610,8 @@@
      }
      StageUtils.useAmbariJdkInCommandParams(commandParams, configs);
  
 -    String repoInfo;
 -    try {
 -      repoInfo = repoVersionHelper.getRepoInfo(cluster, component, host);
 -    } catch (SystemException e) {
 -      throw new AmbariException("", e);
 -    }
++    // TODO add TODO to ambariMetaInfo.getRepoInfoString
 +    String repoInfo = ambariMetaInfo.getRepoInfoString(cluster, component, host);
      if (LOG.isDebugEnabled()) {
        LOG.debug("Sending repo information to agent, hostname={}, clusterName={}, stackInfo={}, repoInfo={}",
          scHost.getHostName(), clusterName, stackId.getStackId(), repoInfo);
@@@ -2665,9 -2572,9 +2681,10 @@@
      execCmd.setRoleParams(roleParams);
      execCmd.setCommandParams(commandParams);
  
 +    execCmd.setRepositoryFile(ambariMetaInfo.getCommandRepository(cluster, component, host));
+     execCmdWrapper.setVersions(cluster);
  
 -    if (execCmd.getConfigurationTags().containsKey("cluster-env")) {
 +    if ((execCmd != null) && (execCmd.getConfigurationTags().containsKey("cluster-env"))) {
        LOG.debug("AmbariManagementControllerImpl.createHostAction: created ExecutionCommand for host {}, role {}, roleCommand {}, and command ID {}, with cluster-env tags {}",
          execCmd.getHostname(), execCmd.getRole(), execCmd.getRoleCommand(), execCmd.getCommandId(), execCmd.getConfigurationTags().get("cluster-env").get("tag"));
      }
@@@ -5802,259 -5649,4 +5767,259 @@@
      return QuickLinkVisibilityControllerFactory.get(quickLinkProfileJson);
    }
  
 +  /**
 +   * Collects metadata info about clusters for agent.
 +   * @return metadata info about clusters
 +   * @throws AmbariException
 +   */
 +  public MetadataUpdateEvent getClustersMetadata() throws AmbariException {
 +    TreeMap<String, MetadataCluster> metadataClusters = new TreeMap<>();
 +
 +    for (Cluster cl : clusters.getClusters().values()) {
 +      StackId stackId = cl.getDesiredStackVersion();
 +
 +      SecurityType securityType = cl.getSecurityType();
 +
 +      TreeMap<String, MetadataServiceInfo> serviceLevelParams = new TreeMap<>();
 +      Collection<ServiceInfo> servicesInfo = ambariMetaInfo.getServices(stackId.getStackName(),
 +          stackId.getStackVersion()).values();
 +      for (ServiceInfo serviceInfo : servicesInfo) {
 +        Long statusCommandTimeout = null;
 +        if (serviceInfo.getCommandScript() != null) {
 +          statusCommandTimeout = new Long (ambariCustomCommandExecutionHelper.getStatusCommandTimeout(serviceInfo));
 +        }
 +
 +        String servicePackageFolder = serviceInfo.getServicePackageFolder();
 +
 +        serviceLevelParams.put(serviceInfo.getName(),
 +            new MetadataServiceInfo(serviceInfo.getVersion(),
 +                serviceInfo.isCredentialStoreEnabled(),
 +                statusCommandTimeout,
 +                servicePackageFolder));
 +      }
 +
 +      MetadataCluster metadataCluster = new MetadataCluster(securityType,
 +          serviceLevelParams,
 +          getMetadataClusterLevelParams(cl, stackId));
 +      metadataClusters.put(Long.toString(cl.getClusterId()), metadataCluster);
 +    }
 +
 +    MetadataUpdateEvent metadataUpdateEvent = new MetadataUpdateEvent(metadataClusters,
 +        getMetadataAmbariLevelParams());
 +    return metadataUpdateEvent;
 +  }
 +
 +  public MetadataUpdateEvent getClusterMetadata(Cluster cl) throws AmbariException {
 +    TreeMap<String, MetadataCluster> metadataClusters = new TreeMap<>();
 +    StackId stackId = cl.getDesiredStackVersion();
 +
 +    SecurityType securityType = cl.getSecurityType();
 +
 +    TreeMap<String, MetadataServiceInfo> serviceLevelParams = new TreeMap<>();
 +    Collection<ServiceInfo> servicesInfo = ambariMetaInfo.getServices(stackId.getStackName(),
 +        stackId.getStackVersion()).values();
 +    for (ServiceInfo serviceInfo : servicesInfo) {
 +      Long statusCommandTimeout = null;
 +      if (serviceInfo.getCommandScript() != null) {
 +        statusCommandTimeout = new Long(ambariCustomCommandExecutionHelper.getStatusCommandTimeout(serviceInfo));
 +      }
 +
 +      String servicePackageFolder = serviceInfo.getServicePackageFolder();
 +
 +      serviceLevelParams.put(serviceInfo.getName(),
 +          new MetadataServiceInfo(serviceInfo.getVersion(),
 +              serviceInfo.isCredentialStoreEnabled(),
 +              statusCommandTimeout,
 +              servicePackageFolder));
 +    }
 +
 +    MetadataCluster metadataCluster = new MetadataCluster(securityType,
 +        serviceLevelParams,
 +        getMetadataClusterLevelParams(cl, stackId));
 +    metadataClusters.put(Long.toString(cl.getClusterId()), metadataCluster);
 +
 +    MetadataUpdateEvent metadataUpdateEvent = new MetadataUpdateEvent(metadataClusters,
 +        null);
 +    return metadataUpdateEvent;
 +  }
 +
 +  public MetadataUpdateEvent getClusterMetadataOnConfigsUpdate(Cluster cl) throws AmbariException {
 +    TreeMap<String, MetadataCluster> metadataClusters = new TreeMap<>();
 +    StackId stackId = cl.getDesiredStackVersion();
 +
 +    MetadataCluster metadataCluster = new MetadataCluster(null,
 +        new TreeMap<>(),
 +        getMetadataClusterLevelConfigsParams(cl, stackId));
 +    metadataClusters.put(Long.toString(cl.getClusterId()), metadataCluster);
 +
 +    MetadataUpdateEvent metadataUpdateEvent = new MetadataUpdateEvent(metadataClusters,
 +        null);
 +    return metadataUpdateEvent;
 +  }
 +
 +  private String getClientsToUpdateConfigs(ComponentInfo componentInfo) {
 +    List<String> clientsToUpdateConfigsList = componentInfo.getClientsToUpdateConfigs();
 +    if (clientsToUpdateConfigsList == null) {
 +      clientsToUpdateConfigsList = new ArrayList<>();
 +      clientsToUpdateConfigsList.add("*");
 +    }
 +    return gson.toJson(clientsToUpdateConfigsList);
 +  }
 +
 +  private Boolean getUnlimitedKeyJCERequirement(ComponentInfo componentInfo, SecurityType clusterSecurityType) {
 +    UnlimitedKeyJCERequirement unlimitedKeyJCERequirement = componentInfo.getUnlimitedKeyJCERequired();
 +    // Ensure that the unlimited key requirement is set. If null, the default value should be used.
 +    if(unlimitedKeyJCERequirement == null) {
 +      unlimitedKeyJCERequirement = UnlimitedKeyJCERequirement.DEFAULT;
 +    }
 +
 +    return (UnlimitedKeyJCERequirement.ALWAYS == unlimitedKeyJCERequirement) ||
 +        ((UnlimitedKeyJCERequirement.KERBEROS_ENABLED == unlimitedKeyJCERequirement) &&
 +            (clusterSecurityType == SecurityType.KERBEROS));
 +
 +  }
 +
 +  //TODO will be a need to change to multi-instance usage
 +  public TreeMap<String, String> getTopologyComponentLevelParams(StackId stackId, String serviceName, String componentName,
 +                                                             SecurityType clusterSecurityType) throws AmbariException {
 +    ComponentInfo componentInfo = ambariMetaInfo.getComponent(
 +        stackId.getStackName(), stackId.getStackVersion(),
 +        serviceName, componentName);
 +
 +    TreeMap<String, String> statusCommandParams = new TreeMap<>();
 +    statusCommandParams.put(ExecutionCommand.KeyNames.CLIENTS_TO_UPDATE_CONFIGS,
 +        getClientsToUpdateConfigs(componentInfo));
 +    statusCommandParams.put(ExecutionCommand.KeyNames.UNLIMITED_KEY_JCE_REQUIRED,
 +         Boolean.toString(getUnlimitedKeyJCERequirement(componentInfo, clusterSecurityType)));
 +    return statusCommandParams;
 +  }
 +
 +  //TODO will be a need to change to multi-instance usage
 +  public TreeMap<String, String> getTopologyCommandParams(StackId stackId, String serviceName, String componentName) throws AmbariException {
 +    ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
 +        stackId.getStackVersion(), serviceName);
 +    ComponentInfo componentInfo = ambariMetaInfo.getComponent(
 +        stackId.getStackName(), stackId.getStackVersion(),
 +        serviceName, componentName);
 +
 +    String scriptName = null;
 +    String scriptCommandTimeout = "";
 +    CommandScriptDefinition script = componentInfo.getCommandScript();
 +    if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
 +      if (script != null) {
 +        scriptName = script.getScript();
 +        if (script.getTimeout() > 0) {
 +          scriptCommandTimeout = String.valueOf(script.getTimeout());
 +        }
 +      } else {
 +        String message = String.format("Component %s of service %s has not " +
 +            "command script defined", componentName, serviceName);
 +        throw new AmbariException(message);
 +      }
 +    }
 +    String agentDefaultCommandTimeout = configs.getDefaultAgentTaskTimeout(false);
 +    String actualTimeout = (!scriptCommandTimeout.equals("") ? scriptCommandTimeout : agentDefaultCommandTimeout);
 +
 +    TreeMap<String, String> commandParams = new TreeMap<>();
 +    commandParams.put(COMMAND_TIMEOUT, actualTimeout);
 +    commandParams.put(SCRIPT, scriptName);
 +    commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
 +    return commandParams;
 +  }
 +
 +  public TreeMap<String, String> getMetadataClusterLevelParams(Cluster cluster, StackId stackId) throws AmbariException {
 +    TreeMap<String, String> clusterLevelParams = new TreeMap<>();
 +    clusterLevelParams.put(STACK_NAME, stackId.getStackName());
 +    clusterLevelParams.put(STACK_VERSION, stackId.getStackVersion());
 +
 +    Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
 +    if (MapUtils.isNotEmpty(desiredConfigs)) {
 +
 +      Set<String> userSet = configHelper.getPropertyValuesWithPropertyType(stackId, PropertyType.USER, cluster, desiredConfigs);
 +      String userList = gson.toJson(userSet);
 +      clusterLevelParams.put(USER_LIST, userList);
 +
 +      //Create a user_group mapping and send it as part of the hostLevelParams
 +      Map<String, Set<String>> userGroupsMap = configHelper.createUserGroupsMap(
 +          stackId, cluster, desiredConfigs);
 +      String userGroups = gson.toJson(userGroupsMap);
 +      clusterLevelParams.put(USER_GROUPS, userGroups);
 +
 +      Set<String> groupSet = configHelper.getPropertyValuesWithPropertyType(stackId, PropertyType.GROUP, cluster, desiredConfigs);
 +      String groupList = gson.toJson(groupSet);
 +      clusterLevelParams.put(GROUP_LIST, groupList);
 +    }
 +    Set<String> notManagedHdfsPathSet = configHelper.getPropertyValuesWithPropertyType(stackId,
 +        PropertyType.NOT_MANAGED_HDFS_PATH, cluster, desiredConfigs);
 +    String notManagedHdfsPathList = gson.toJson(notManagedHdfsPathSet);
 +    clusterLevelParams.put(NOT_MANAGED_HDFS_PATH_LIST, notManagedHdfsPathList);
 +
 +    clusterLevelParams.put(CLUSTER_NAME, cluster.getClusterName());
 +
 +    StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion());
-     clusterLevelParams.put(HOOKS_FOLDER, StackManager.DEFAULT_HOOKS_FOLDER);
++    clusterLevelParams.put(HOOKS_FOLDER, configs.getProperty(Configuration.HOOKS_FOLDER));
 +
 +    return clusterLevelParams;
 +  }
 +
 +  public TreeMap<String, String> getMetadataClusterLevelConfigsParams(Cluster cluster, StackId stackId) throws AmbariException {
 +    TreeMap<String, String> clusterLevelParams = new TreeMap<>();
 +
 +    Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
 +    if (MapUtils.isNotEmpty(desiredConfigs)) {
 +
 +      Set<String> userSet = configHelper.getPropertyValuesWithPropertyType(stackId, PropertyType.USER, cluster, desiredConfigs);
 +      String userList = gson.toJson(userSet);
 +      clusterLevelParams.put(USER_LIST, userList);
 +
 +      //Create a user_group mapping and send it as part of the hostLevelParams
 +      Map<String, Set<String>> userGroupsMap = configHelper.createUserGroupsMap(
 +          stackId, cluster, desiredConfigs);
 +      String userGroups = gson.toJson(userGroupsMap);
 +      clusterLevelParams.put(USER_GROUPS, userGroups);
 +
 +      Set<String> groupSet = configHelper.getPropertyValuesWithPropertyType(stackId, PropertyType.GROUP, cluster, desiredConfigs);
 +      String groupList = gson.toJson(groupSet);
 +      clusterLevelParams.put(GROUP_LIST, groupList);
 +    }
 +    Set<String> notManagedHdfsPathSet = configHelper.getPropertyValuesWithPropertyType(stackId,
 +        PropertyType.NOT_MANAGED_HDFS_PATH, cluster, desiredConfigs);
 +    String notManagedHdfsPathList = gson.toJson(notManagedHdfsPathSet);
 +    clusterLevelParams.put(NOT_MANAGED_HDFS_PATH_LIST, notManagedHdfsPathList);
 +
 +    return clusterLevelParams;
 +  }
 +
 +  public TreeMap<String, String> getMetadataAmbariLevelParams() throws AmbariException {
 +    TreeMap<String, String> clusterLevelParams = new TreeMap<>();
 +    clusterLevelParams.put(JDK_LOCATION, getJdkResourceUrl());
 +    clusterLevelParams.put(JAVA_HOME, getJavaHome());
 +    clusterLevelParams.put(JAVA_VERSION, String.valueOf(configs.getJavaVersion()));
 +    clusterLevelParams.put(JDK_NAME, getJDKName());
 +    clusterLevelParams.put(JCE_NAME, getJCEName());
 +    clusterLevelParams.put(DB_NAME, getServerDB());
 +    clusterLevelParams.put(MYSQL_JDBC_URL, getMysqljdbcUrl());
 +    clusterLevelParams.put(ORACLE_JDBC_URL, getOjdbcUrl());
 +    clusterLevelParams.put(DB_DRIVER_FILENAME, configs.getMySQLJarName());
 +    clusterLevelParams.putAll(getRcaParameters());
 +    clusterLevelParams.put(HOST_SYS_PREPPED, configs.areHostsSysPrepped());
 +    clusterLevelParams.put(AGENT_STACK_RETRY_ON_UNAVAILABILITY, configs.isAgentStackRetryOnInstallEnabled());
 +    clusterLevelParams.put(AGENT_STACK_RETRY_COUNT, configs.getAgentStackRetryOnInstallCount());
 +
 +    return clusterLevelParams;
 +  }
 +
 +  @Override
 +  public HostRepositories retrieveHostRepositories(Cluster cluster, Host host) throws AmbariException {
 +    List<ServiceComponentHost> hostComponents = cluster.getServiceComponentHosts(host.getHostName());
 +    Map<Long, CommandRepository> hostRepositories = new HashMap<>();
 +    Map<String, Long> componentsRepos = new HashMap<>();
 +    for (ServiceComponentHost serviceComponentHost : hostComponents) {
 +      CommandRepository commandRepository = ambariMetaInfo.getCommandRepository(cluster,
 +          serviceComponentHost.getServiceComponent(), host);
 +      hostRepositories.put(commandRepository.getM_repoVersionId(), commandRepository);
 +      componentsRepos.put(serviceComponentHost.getServiceComponentName(), commandRepository.getM_repoVersionId());
 +    }
 +    return new HostRepositories(hostRepositories, componentsRepos);
 +  }
  }

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index 99ecd76,482e5d2..759ec82
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@@ -60,12 -60,12 +60,14 @@@ import org.apache.ambari.server.state.S
  import org.apache.ambari.server.state.ServiceComponentHost;
  import org.apache.ambari.server.state.StackId;
  import org.apache.ambari.server.state.State;
 +import org.apache.ambari.server.topology.TopologyDeleteFormer;
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.lang.Validate;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
  
  import com.google.common.collect.Sets;
 +import com.google.inject.Inject;
  import com.google.inject.assistedinject.Assisted;
  import com.google.inject.assistedinject.AssistedInject;
  import com.google.inject.persist.Transactional;

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
index 5cc360f,5c740f1..519794e
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
@@@ -1034,12 -956,9 +1030,12 @@@ public class HostResourceProvider exten
        }
      }
      clusters.publishHostsDeletion(allClustersWithHosts, hostNames);
 +    TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(topologyUpdates,
 +        TopologyUpdateEvent.EventType.DELETE);
 +    topologyHolder.updateData(topologyUpdateEvent);
    }
  
-   private void validateHostInDeleteFriendlyState(HostRequest hostRequest, Clusters clusters, boolean forceDelete) throws AmbariException {
+   private void validateHostInDeleteFriendlyState(HostRequest hostRequest, Clusters clusters) throws AmbariException {
      Set<String> clusterNamesForHost = new HashSet<>();
      String hostName = hostRequest.getHostname();
      if (null != hostRequest.getClusterName()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/DefaultServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/FlumeServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/HBaseServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/HDFSServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/HiveServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/OozieServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/state/YARNServiceCalculatedState.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
index 47c83e7,0ece73b..5f410f5
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
@@@ -143,19 -143,10 +143,24 @@@ public abstract class AmbariEvent 
      USER_CREATED,
  
      /**
 +     * Host status has been changed.
 +     */
 +    HOST_STATUS_CHANGE,
 +
 +    /**
 +     * Host state has been changed.
 +     */
 +    HOST_STATE_CHANGE,
 +
 +    /**
 +     * Received new heartbeat with host info.
 +     */
-     HOST_HEARTBEAT_UPDATED;
++    HOST_HEARTBEAT_UPDATED,
++
++    /**
+      * Ambari configuration changed event;
+      */
+     AMBARI_CONFIGURATION_CHANGED;
 -
    }
  
    /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
index 3e4d6a2,b91135f..b4ae216
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
@@@ -27,11 -27,21 +27,12 @@@ public class ServiceComponentUninstalle
    private final String m_componentName;
    private final String m_hostName;
    private final boolean m_recoveryEnabled;
 +  private final boolean masterComponent;
+   private final Long m_hostId;
  
 -  /**
 -   * Constructor.
 -   *
 -   * @param clusterId
 -   * @param stackName
 -   * @param stackVersion
 -   * @param serviceName
 -   * @param componentName
 -   * @param hostName
 -   */
    public ServiceComponentUninstalledEvent(long clusterId, String stackName,
        String stackVersion, String serviceName, String componentName,
-       String hostName, boolean recoveryEnabled, boolean masterComponent) {
 -      String hostName, boolean recoveryEnabled, Long hostId) {
++      String hostName, boolean recoveryEnabled, boolean masterComponent, Long hostId) {
      super(AmbariEventType.SERVICE_COMPONENT_UNINSTALLED_SUCCESS, clusterId,
          stackName,
          stackVersion, serviceName);
@@@ -39,7 -49,7 +40,8 @@@
      m_componentName = componentName;
      m_hostName = hostName;
      m_recoveryEnabled = recoveryEnabled;
 +    this.masterComponent = masterComponent;
+     m_hostId = hostId;
    }
  
    /**
@@@ -63,10 -73,10 +65,14 @@@
      return m_recoveryEnabled;
    }
  
 +  public boolean isMasterComponent() {
 +    return masterComponent;
 +  }
 +
+   public Long getHostId() {
+     return m_hostId;
+   }
+ 
    /**
     * {@inheritDoc}
     */

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
index 33f172c,7198814..5aba046
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
@@@ -26,11 -24,10 +26,11 @@@ import java.util.concurrent.locks.Lock
  
  import org.apache.ambari.server.AmbariException;
  import org.apache.ambari.server.EagerSingleton;
 +import org.apache.ambari.server.api.query.render.AlertSummaryGroupedRenderer;
  import org.apache.ambari.server.configuration.Configuration;
  import org.apache.ambari.server.controller.MaintenanceStateHelper;
- import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
- import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
+ import org.apache.ambari.server.controller.RootComponent;
+ import org.apache.ambari.server.controller.RootService;
  import org.apache.ambari.server.events.AlertEvent;
  import org.apache.ambari.server.events.AlertReceivedEvent;
  import org.apache.ambari.server.events.AlertStateChangeEvent;

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index bbbb613,8f5e4f4..b634fb2
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@@ -58,9 -57,8 +58,9 @@@ import org.apache.ambari.server.control
  import org.apache.ambari.server.controller.ClusterResponse;
  import org.apache.ambari.server.controller.ConfigurationResponse;
  import org.apache.ambari.server.controller.MaintenanceStateHelper;
- import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
+ import org.apache.ambari.server.controller.RootService;
  import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
 +import org.apache.ambari.server.controller.internal.DeleteHostComponentStatusMetaData;
  import org.apache.ambari.server.events.AmbariEvent.AmbariEventType;
  import org.apache.ambari.server.events.ClusterConfigChangedEvent;
  import org.apache.ambari.server.events.ClusterEvent;

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
index 22bcfc7,e30c2ce..ef7d471
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
@@@ -21,14 -21,11 +21,14 @@@ package org.apache.ambari.server.state.
  import java.text.MessageFormat;
  import java.util.Collections;
  import java.util.HashMap;
 -import java.util.List;
 +import java.util.HashSet;
- import java.util.List;
++ import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
 +import java.util.TreeMap;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
 +import java.util.concurrent.atomic.AtomicReference;
  import java.util.concurrent.locks.Lock;
  import java.util.concurrent.locks.ReadWriteLock;
  import java.util.concurrent.locks.ReentrantReadWriteLock;
@@@ -1387,15 -1280,9 +1387,15 @@@ public class ServiceComponentHostImpl i
  
        ServiceComponentUninstalledEvent event = new ServiceComponentUninstalledEvent(
            clusterId, stackName, stackVersion, serviceName, componentName,
-           hostName, recoveryEnabled, masterComponent);
 -          hostName, recoveryEnabled, host.getHostId());
++          hostName, recoveryEnabled, masterComponent, host.getHostId());
  
        eventPublisher.publish(event);
 +      deleteMetaData.addDeletedHostComponent(componentName,
 +          serviceName,
 +          hostName,
 +          getHost().getHostId(),
 +          Long.toString(clusterId),
 +          version);
      }
    }
  

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
index be6b960,2de6095..1ee1679
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
@@@ -47,7 -45,7 +47,8 @@@ import org.apache.ambari.server.state.C
  import org.apache.ambari.server.state.Clusters;
  import org.apache.ambari.server.state.Config;
  import org.apache.ambari.server.state.ConfigHelper;
+ import org.apache.commons.collections.MapUtils;
 +import org.apache.ambari.server.state.State;
  import org.apache.commons.lang.StringUtils;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
@@@ -68,15 -66,10 +69,11 @@@ public class UpgradeCatalog300 extends 
    protected static final String STAGE_DISPLAY_STATUS_COLUMN = "display_status";
    protected static final String REQUEST_TABLE = "request";
    protected static final String REQUEST_DISPLAY_STATUS_COLUMN = "display_status";
-   protected static final String CLUSTER_CONFIG_TABLE = "clusterconfig";
-   protected static final String CLUSTER_CONFIG_SELECTED_COLUMN = "selected";
-   protected static final String CLUSTER_CONFIG_SELECTED_TIMESTAMP_COLUMN = "selected_timestamp";
    protected static final String HOST_ROLE_COMMAND_TABLE = "host_role_command";
    protected static final String HRC_OPS_DISPLAY_NAME_COLUMN = "ops_display_name";
-   protected static final String COMPONENT_TABLE = "servicecomponentdesiredstate";
    protected static final String COMPONENT_DESIRED_STATE_TABLE = "hostcomponentdesiredstate";
    protected static final String COMPONENT_STATE_TABLE = "hostcomponentstate";
 +  protected static final String COMPONENT_LAST_STATE_COLUMN = "last_live_state";
    protected static final String SERVICE_DESIRED_STATE_TABLE = "servicedesiredstate";
    protected static final String SECURITY_STATE_COLUMN = "security_state";
  
@@@ -126,7 -123,7 +127,8 @@@
      updateStageTable();
      addOpsDisplayNameColumnToHostRoleCommand();
      removeSecurityState();
+     addAmbariConfigurationTable();
 +    addHostComponentLastStateTable();
    }
  
    protected void updateStageTable() throws SQLException {
@@@ -138,11 -135,16 +140,21 @@@
          new DBAccessor.DBColumnInfo(REQUEST_DISPLAY_STATUS_COLUMN, String.class, 255, HostRoleStatus.PENDING, false));
    }
  
+   protected void addAmbariConfigurationTable() throws SQLException {
+     List<DBAccessor.DBColumnInfo> columns = new ArrayList<>();
+     columns.add(new DBAccessor.DBColumnInfo(AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN, String.class, 100, null, false));
+     columns.add(new DBAccessor.DBColumnInfo(AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN, String.class, 100, null, false));
+     columns.add(new DBAccessor.DBColumnInfo(AMBARI_CONFIGURATION_PROPERTY_VALUE_COLUMN, String.class, 255, null, true));
+ 
+     dbAccessor.createTable(AMBARI_CONFIGURATION_TABLE, columns);
+     dbAccessor.addPKConstraint(AMBARI_CONFIGURATION_TABLE, "PK_ambari_configuration", AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN, AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN);
+   }
+ 
 +  protected void addHostComponentLastStateTable() throws SQLException {
 +    dbAccessor.addColumn(COMPONENT_STATE_TABLE,
 +        new DBAccessor.DBColumnInfo(COMPONENT_LAST_STATE_COLUMN, String.class, 255, State.UNKNOWN, true));
 +  }
 +
    /**
     * {@inheritDoc}
     */
@@@ -159,7 -161,7 +171,8 @@@
      showHcatDeletedUserMessage();
      setStatusOfStagesAndRequests();
      updateLogSearchConfigs();
+     updateKerberosConfigurations();
 +    updateHostComponentLastStateTable();
    }
  
    protected void showHcatDeletedUserMessage() {
@@@ -358,21 -360,27 +371,45 @@@
      }
    }
  
+   protected void updateKerberosConfigurations() throws AmbariException {
+     AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+     Clusters clusters = ambariManagementController.getClusters();
+     if (clusters != null) {
+       Map<String, Cluster> clusterMap = clusters.getClusters();
+ 
+       if (!MapUtils.isEmpty(clusterMap)) {
+         for (Cluster cluster : clusterMap.values()) {
+           Config config = cluster.getDesiredConfigByType("kerberos-env");
+ 
+           if (config != null) {
+             Map<String, String> properties = config.getProperties();
+             if (properties.containsKey("group")) {
+               // Covert kerberos-env/group to kerberos-env/ipa_user_group
+               updateConfigurationPropertiesForCluster(cluster, "kerberos-env",
+                   Collections.singletonMap("ipa_user_group", properties.get("group")), Collections.singleton("group"),
+                   true, false);
+             }
+           }
+         }
+       }
+     }
+   }
++
 +  protected void updateHostComponentLastStateTable() throws SQLException {
 +    executeInTransaction(new Runnable() {
 +      @Override
 +      public void run() {
 +        try {
 +          HostComponentStateDAO hostComponentStateDAO = injector.getInstance(HostComponentStateDAO.class);
 +          List<HostComponentStateEntity> hostComponentStateEntities = hostComponentStateDAO.findAll();
 +          for (HostComponentStateEntity hostComponentStateEntity : hostComponentStateEntities) {
 +            hostComponentStateEntity.setLastLiveState(hostComponentStateEntity.getCurrentState());
 +            hostComponentStateDAO.merge(hostComponentStateEntity);
 +          }
 +        } catch (Exception e) {
 +          LOG.warn("Setting status for stages and Requests threw exception. ", e);
 +        }
 +      }
 +    });
 +  }
  }

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------


[50/50] [abbrv] ambari git commit: Merge branch 'trunk' into branch-3.0-perf

Posted by ao...@apache.org.
Merge branch 'trunk' into branch-3.0-perf


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/366f6ca9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/366f6ca9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/366f6ca9

Branch: refs/heads/branch-3.0-perf
Commit: 366f6ca9bd8eec1dd03a735a67158956c2426a31
Parents: eaf1fd5 c3150a4
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Thu Dec 7 16:02:06 2017 +0200
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Thu Dec 7 16:02:06 2017 +0200

----------------------------------------------------------------------
 .gitignore                                      |     3 +
 ambari-admin/pom.xml                            |     2 +-
 .../app/assets/fonts/Roboto-Regular-webfont.eot |   Bin 0 -> 79547 bytes
 .../app/assets/fonts/Roboto-Regular-webfont.svg |  7606 ++++++
 .../app/assets/fonts/Roboto-Regular-webfont.ttf |   Bin 0 -> 234464 bytes
 .../assets/fonts/Roboto-Regular-webfont.woff    |   Bin 0 -> 105700 bytes
 .../main/resources/ui/admin-web/app/index.html  |    97 +-
 .../resources/ui/admin-web/app/scripts/app.js   |     3 +-
 .../app/scripts/controllers/AppCtrl.js          |   177 +
 .../app/scripts/controllers/NavbarCtrl.js       |   106 -
 .../app/scripts/controllers/SideNavCtrl.js      |    68 +
 .../ambariViews/CreateViewInstanceCtrl.js       |   406 +-
 .../controllers/ambariViews/ViewsListCtrl.js    |   361 +-
 .../clusters/ClusterInformationCtrl.js          |   106 +
 .../clusters/ClustersManageAccessCtrl.js        |    97 -
 .../controllers/clusters/ExportBlueprintCtrl.js |    58 -
 .../controllers/clusters/UserAccessListCtrl.js  |   351 -
 .../controllers/groups/GroupsCreateCtrl.js      |    65 -
 .../controllers/groups/GroupsEditCtrl.js        |   180 -
 .../controllers/groups/GroupsListCtrl.js        |   106 -
 .../app/scripts/controllers/mainCtrl.js         |   183 -
 .../stackVersions/StackVersionsEditCtrl.js      |    27 +-
 .../userManagement/GroupCreateCtrl.js           |   120 +
 .../controllers/userManagement/GroupEditCtrl.js |   248 +
 .../userManagement/GroupsListCtrl.js            |   167 +
 .../userManagement/UserCreateCtrl.js            |   113 +
 .../controllers/userManagement/UserEditCtrl.js  |   364 +
 .../userManagement/UserManagementCtrl.js        |    23 +
 .../controllers/userManagement/UsersListCtrl.js |   177 +
 .../controllers/users/UsersCreateCtrl.js        |    75 -
 .../scripts/controllers/users/UsersListCtrl.js  |   122 -
 .../scripts/controllers/users/UsersShowCtrl.js  |   290 -
 .../ui/admin-web/app/scripts/i18n.config.js     |    49 +-
 .../ui/admin-web/app/scripts/routes.js          |   161 +-
 .../admin-web/app/scripts/services/Cluster.js   |    90 +-
 .../ui/admin-web/app/scripts/services/Group.js  |   144 +-
 .../app/scripts/services/GroupConstants.js      |    38 -
 .../app/scripts/services/RoleDetailsModal.js    |     5 +-
 .../ui/admin-web/app/scripts/services/Stack.js  |    17 +-
 .../ui/admin-web/app/scripts/services/User.js   |    20 +-
 .../ui/admin-web/app/scripts/services/View.js   |    40 +-
 .../app/scripts/theme/bootstrap-ambari.js       |   269 +
 .../app/styles/cluster-information.css          |    58 +
 .../resources/ui/admin-web/app/styles/main.css  |   696 +-
 .../app/styles/theme/bootstrap-ambari.css       |  1518 ++
 .../ui/admin-web/app/styles/toggle-switch.css   |    72 +
 .../ui/admin-web/app/styles/top-nav.css         |   200 +
 .../ui/admin-web/app/styles/user-management.css |    43 +
 .../resources/ui/admin-web/app/styles/views.css |   105 +
 .../admin-web/app/views/ambariViews/create.html |   204 -
 .../admin-web/app/views/ambariViews/edit.html   |    37 +-
 .../app/views/ambariViews/listTable.html        |   110 -
 .../app/views/ambariViews/listUrls.html         |   117 -
 .../app/views/ambariViews/modals/create.html    |   312 +-
 .../app/views/ambariViews/modals/edit.html      |   138 -
 .../app/views/ambariViews/viewsList.html        |   151 +
 .../app/views/authentication/main.html          |    14 +-
 .../app/views/clusters/clusterInformation.html  |    87 +
 .../app/views/clusters/exportBlueprint.html     |    40 -
 .../app/views/clusters/manageAccess.html        |    63 -
 .../app/views/clusters/userAccessList.html      |   102 -
 .../ui/admin-web/app/views/groups/create.html   |    43 -
 .../ui/admin-web/app/views/groups/edit.html     |    98 -
 .../ui/admin-web/app/views/groups/list.html     |    79 -
 .../ui/admin-web/app/views/leftNavbar.html      |   126 -
 .../views/loginActivities/homeDirectory.html    |     6 +-
 .../app/views/loginActivities/loginMessage.html |     6 +-
 .../resources/ui/admin-web/app/views/main.html  |    96 -
 .../app/views/modals/AddVersionModal.html       |    14 +-
 .../app/views/remoteClusters/list.html          |    11 +-
 .../ui/admin-web/app/views/sideNav.html         |    99 +
 .../admin-web/app/views/stackVersions/list.html |    22 +-
 .../views/stackVersions/stackVersionPage.html   |    55 +-
 .../ui/admin-web/app/views/urls/create.html     |     6 +-
 .../ui/admin-web/app/views/urls/edit.html       |     6 +-
 .../app/views/userManagement/groupEdit.html     |   122 +
 .../app/views/userManagement/groupsList.html    |    94 +
 .../app/views/userManagement/main.html          |    36 +
 .../userManagement/modals/changePassword.html   |    46 +
 .../userManagement/modals/groupCreate.html      |    87 +
 .../views/userManagement/modals/userCreate.html |   152 +
 .../app/views/userManagement/userEdit.html      |   144 +
 .../app/views/userManagement/usersList.html     |   119 +
 .../ui/admin-web/app/views/users/create.html    |    82 -
 .../ui/admin-web/app/views/users/list.html      |    96 -
 .../app/views/users/modals/changePassword.html  |    46 -
 .../ui/admin-web/app/views/users/show.html      |   122 -
 .../src/main/resources/ui/admin-web/bower.json  |     2 +-
 .../src/main/resources/ui/admin-web/gulpfile.js |    10 +-
 .../main/resources/ui/admin-web/package.json    |     6 +-
 .../test/unit/controllers/AppCtrl_test.js       |   211 +
 .../controllers/ClusterInformationCtrl_test.js  |   102 +
 .../unit/controllers/CreateViewInstanceCtrl.js  |   135 -
 .../clusters/UserAccessListCtrl_test.js         |   820 -
 .../controllers/groups/GroupsListCtrl_test.js   |   129 -
 .../test/unit/controllers/mainCtrl_test.js      |   215 -
 .../userManagement/GroupsListCtrl_test.js       |   129 +
 .../userManagement/UsersListCtrl_test.js        |   344 +
 .../controllers/users/UsersListCtrl_test.js     |   383 -
 .../test/unit/services/Utility_test.js          |    11 +-
 .../src/main/python/ambari_agent/ActionQueue.py |     5 +-
 .../src/main/python/ambari_agent/AmbariAgent.py |     3 -
 .../src/main/python/ambari_agent/Hardware.py    |   130 +-
 .../src/main/python/ambari_agent/Heartbeat.py   |     8 +-
 .../src/main/python/ambari_agent/HostInfo.py    |    85 +-
 .../python/ambari_agent/alerts/base_alert.py    |     2 +-
 .../test/python/ambari_agent/TestAmbariAgent.py |     4 +-
 .../test/python/ambari_agent/TestHardware.py    |    56 +-
 .../python/ambari_agent/TestRegistration.py     |     5 +-
 .../core/providers/package/__init__.py          |     2 +-
 .../core/providers/package/apt.py               |    23 +-
 .../core/providers/package/yumrpm.py            |    85 +-
 .../core/providers/package/zypper.py            |    37 +-
 .../libraries/functions/__init__.py             |     2 +-
 .../libraries/functions/component_version.py    |     9 +-
 .../libraries/functions/conf_select.py          |    58 +
 .../libraries/functions/copy_tarball.py         |   201 +-
 .../libraries/functions/curl_krb_request.py     |    22 +-
 .../libraries/functions/get_lzo_packages.py     |    50 -
 .../libraries/functions/lzo_utils.py            |    93 +
 .../libraries/functions/package_conditions.py   |    14 +-
 .../libraries/functions/repository_util.py      |    79 +-
 .../libraries/functions/stack_select.py         |     3 +-
 .../libraries/functions/tar_archive.py          |     6 +-
 .../libraries/script/script.py                  |     3 +-
 ambari-funtest/pom.xml                          |    67 -
 ambari-infra/ambari-infra-manager/pom.xml       |    11 +
 .../infra/job/archive/CompositeFileAction.java  |    46 +
 .../ambari/infra/job/archive/Document.java      |    54 +
 .../infra/job/archive/DocumentDestination.java  |    23 +
 .../archive/DocumentExportConfiguration.java    |   118 +
 .../job/archive/DocumentExportJobListener.java  |    35 +
 .../job/archive/DocumentExportProperties.java   |   112 +
 .../job/archive/DocumentExportStepListener.java |    47 +
 .../infra/job/archive/DocumentExporter.java     |    99 +
 .../infra/job/archive/DocumentItemReader.java   |   135 +
 .../infra/job/archive/DocumentItemWriter.java   |    25 +
 .../infra/job/archive/DocumentIterator.java     |    25 +
 .../infra/job/archive/DocumentSource.java       |    24 +
 .../ambari/infra/job/archive/FileAction.java    |    25 +
 .../job/archive/LocalDocumentItemWriter.java    |    72 +
 .../ambari/infra/job/archive/S3Properties.java  |    64 +
 .../ambari/infra/job/archive/S3Uploader.java    |    51 +
 .../infra/job/archive/SolrDocumentIterator.java |    90 +
 .../infra/job/archive/SolrDocumentSource.java   |    68 +
 .../infra/job/archive/SolrQueryBuilder.java     |   115 +
 .../infra/job/archive/SolrQueryProperties.java  |    69 +
 .../infra/job/archive/TarGzCompressor.java      |    50 +
 .../apache/ambari/infra/manager/JobManager.java |    21 +-
 .../src/main/resources/infra-manager.properties |    12 +
 .../src/main/resources/log4j2.xml               |     2 +-
 .../infra/job/archive/DocumentExporterTest.java |   147 +
 .../job/archive/DocumentItemReaderTest.java     |   197 +
 .../archive/LocalDocumentItemWriterTest.java    |    98 +
 .../infra/job/archive/SolrQueryBuilderTest.java |   113 +
 .../solr/AmbariSolrCloudClientBuilder.java      |     4 +-
 .../solr/commands/CreateCollectionCommand.java  |    12 +-
 .../infra/solr/commands/CreateShardCommand.java |     5 +-
 .../infra/solr/commands/GetShardsCommand.java   |     2 +-
 ambari-infra/pom.xml                            |     2 +-
 ambari-logsearch/README.md                      |    27 +-
 .../ambari-logsearch-logfeeder/README.md        |    17 +-
 .../ambari-logsearch-logfeeder/pom.xml          |     6 +-
 .../ambari/logfeeder/filter/FilterKeyValue.java |     4 +-
 .../ambari/logfeeder/input/InputFile.java       |     4 +-
 .../logfeeder/metrics/LogFeederAMSClient.java   |     3 +
 .../logfeeder/metrics/MetricsManager.java       |     8 +-
 .../src/main/resources/log-samples/.gitignore   |     4 +
 .../log-samples/logs/service_sample.txt         |     3 +
 .../log-samples/shipper-conf/global.config.json |    10 +
 .../shipper-conf/input.config-sample.json       |    31 +
 .../shipper-conf/output.config-sample.json      |    34 +
 .../src/main/resources/log4j.xml                |     4 +-
 .../src/main/resources/logfeeder.properties     |    31 +-
 .../logfeeder/metrics/MetricsManagerTest.java   |    10 +-
 .../ambari-logsearch-server/.gitignore          |     1 +
 .../ambari-logsearch-server/README.md           |    44 +-
 .../ambari-logsearch-server/pom.xml             |     2 +-
 ambari-logsearch/ambari-logsearch-server/run.sh |     2 +-
 .../configsets/hadoop_logs/conf/managed-schema  |     2 +
 .../ambari/logsearch/conf/AuthPropsConfig.java  |    18 +
 .../ambari/logsearch/conf/SecurityConfig.java   |     6 +-
 .../ambari/logsearch/solr/SolrConstants.java    |     1 +
 .../solr/model/SolrServiceLogData.java          |    17 +
 .../LogsearchAuthenticationEntryPoint.java      |    15 +-
 .../src/main/resources/logsearch.properties     |    54 +-
 .../ambari-logsearch-web/src/app/app.module.ts  |    22 +-
 .../components/logs-table-component.spec.ts     |    61 +
 .../classes/components/logs-table-component.ts  |    51 +
 .../src/app/classes/filtering.ts                |    70 +
 .../src/app/classes/models/app-state.ts         |    15 +-
 .../src/app/classes/models/audit-log.ts         |     2 +-
 .../src/app/classes/models/node-item.ts         |    30 +
 .../src/app/classes/models/node.ts              |    30 -
 .../src/app/classes/models/store.ts             |    18 +-
 .../src/app/classes/models/tab.ts               |    49 +
 .../classes/queries/audit-logs-query-params.ts  |     3 +-
 .../service-logs-truncated-query-params.ts      |     3 +-
 .../src/app/classes/string.ts                   |    25 +
 .../action-menu/action-menu.component.html      |    20 +
 .../action-menu/action-menu.component.less      |    27 +
 .../action-menu/action-menu.component.spec.ts   |    47 +
 .../action-menu/action-menu.component.ts        |   105 +
 .../src/app/components/app.component.html       |     4 +-
 .../src/app/components/app.component.less       |     5 +-
 .../src/app/components/app.component.spec.ts    |     4 +-
 .../src/app/components/app.component.ts         |     6 +-
 .../audit-logs-table.component.html             |    54 +
 .../audit-logs-table.component.less             |    21 +
 .../audit-logs-table.component.spec.ts          |   157 +
 .../audit-logs-table.component.ts               |    55 +
 .../collapsible-panel.component.spec.ts         |    14 +-
 .../date-picker/date-picker.component.spec.ts   |     2 +
 .../date-picker/date-picker.component.ts        |    35 +-
 .../dropdown-button.component.html              |     4 +-
 .../dropdown-button.component.spec.ts           |    24 +-
 .../dropdown-button.component.ts                |    55 +-
 .../dropdown-list/dropdown-list.component.html  |     2 +-
 .../dropdown-list.component.spec.ts             |    15 +-
 .../filter-button.component.spec.ts             |    24 +-
 .../filter-button/filter-button.component.ts    |    35 +-
 .../filter-dropdown.component.spec.ts           |    32 +-
 .../filter-dropdown.component.ts                |    22 +-
 .../filters-panel/filters-panel.component.html  |    31 +-
 .../filters-panel.component.spec.ts             |    12 +-
 .../filters-panel/filters-panel.component.ts    |   109 +-
 .../log-context/log-context.component.spec.ts   |     9 +-
 .../log-level/log-level.component.html          |    18 +
 .../log-level/log-level.component.spec.ts       |    73 +
 .../components/log-level/log-level.component.ts |    52 +
 .../log-message/log-message.component.html      |    24 +
 .../log-message/log-message.component.less      |    69 +
 .../log-message/log-message.component.spec.ts   |    64 +
 .../log-message/log-message.component.ts        |   129 +
 .../login-form/login-form.component.spec.ts     |     7 +-
 .../login-form/login-form.component.ts          |    34 +-
 .../logs-container.component.html               |    56 +-
 .../logs-container.component.less               |    10 +-
 .../logs-container.component.spec.ts            |    13 +-
 .../logs-container/logs-container.component.ts  |   113 +-
 .../logs-list/logs-list.component.html          |    65 -
 .../logs-list/logs-list.component.less          |   109 -
 .../logs-list/logs-list.component.spec.ts       |    95 -
 .../components/logs-list/logs-list.component.ts |   150 -
 .../main-container.component.html               |    10 +-
 .../main-container.component.less               |     4 -
 .../main-container.component.spec.ts            |    15 +-
 .../main-container/main-container.component.ts  |    51 +-
 .../menu-button/menu-button.component.html      |    17 +-
 .../menu-button/menu-button.component.less      |    22 +-
 .../menu-button/menu-button.component.spec.ts   |    24 +-
 .../menu-button/menu-button.component.ts        |   146 +-
 .../src/app/components/mixins.less              |     7 +-
 .../pagination-controls.component.html          |    15 +-
 .../pagination-controls.component.spec.ts       |   101 +
 .../pagination-controls.component.ts            |    76 +-
 .../pagination/pagination.component.html        |     4 +-
 .../pagination/pagination.component.spec.ts     |     9 +-
 .../pagination/pagination.component.ts          |    12 +-
 .../search-box/search-box.component.html        |    24 +-
 .../search-box/search-box.component.less        |    23 +-
 .../search-box/search-box.component.ts          |   130 +-
 .../service-logs-table.component.html           |    76 +
 .../service-logs-table.component.less           |    97 +
 .../service-logs-table.component.spec.ts        |   126 +
 .../service-logs-table.component.ts             |   135 +
 .../src/app/components/tabs/tabs.component.html |    25 +
 .../src/app/components/tabs/tabs.component.less |    22 +
 .../app/components/tabs/tabs.component.spec.ts  |   125 +
 .../src/app/components/tabs/tabs.component.ts   |    48 +
 .../time-histogram.component.less               |     1 +
 .../time-range-picker.component.html            |     9 +-
 .../time-range-picker.component.spec.ts         |    42 +-
 .../time-range-picker.component.ts              |    61 +-
 .../timezone-picker.component.spec.ts           |    24 +-
 .../components/top-menu/top-menu.component.html |    10 +-
 .../components/top-menu/top-menu.component.less |     1 +
 .../components/top-menu/top-menu.component.ts   |    86 +-
 .../src/app/components/variables.less           |     7 +-
 .../ambari-logsearch-web/src/app/mock-data.ts   |     7 +-
 .../src/app/services/auth.service.spec.ts       |   133 +
 .../src/app/services/auth.service.ts            |   123 +
 .../services/component-actions.service.spec.ts  |    15 +-
 .../app/services/component-actions.service.ts   |    69 +-
 .../component-generator.service.spec.ts         |    13 +-
 .../src/app/services/filtering.service.spec.ts  |    94 -
 .../src/app/services/filtering.service.ts       |   566 -
 .../app/services/logs-container.service.spec.ts |    40 +-
 .../src/app/services/logs-container.service.ts  |   834 +-
 .../src/app/services/mock-api-data.service.ts   |    22 +
 .../app/services/storage/reducers.service.ts    |     4 +-
 .../src/app/services/storage/tabs.service.ts    |    33 +
 .../src/app/services/utils.service.spec.ts      |   285 +-
 .../src/app/services/utils.service.ts           |    67 +-
 .../src/assets/i18n/en.json                     |     7 +-
 .../ambari-logsearch-web/webpack.config.js      |    15 +-
 ambari-logsearch/docker/.gitignore              |     1 +
 ambari-logsearch/docker/Dockerfile              |    19 +-
 ambari-logsearch/docker/all.yml                 |    40 +
 ambari-logsearch/docker/bin/start.sh            |    92 +-
 ambari-logsearch/docker/docker-compose.yml      |    89 +
 ambari-logsearch/docker/logsearch-docker.sh     |    51 +-
 ambari-logsearch/docker/logsearch-logfeeder.yml |    35 +
 ambari-logsearch/docker/logsearch-server.yml    |    35 +
 ambari-logsearch/docker/solr.yml                |    34 +
 .../test-config/logfeeder/logfeeder.properties  |     2 +-
 ambari-logsearch/docker/zookeeper.yml           |    52 +
 ambari-logsearch/pom.xml                        |     3 +-
 ambari-metrics/ambari-metrics-assembly/pom.xml  |     1 -
 .../ambari-metrics-hadoop-sink/pom.xml          |     3 +-
 .../timeline/HadoopTimelineMetricsSink.java     |     6 +-
 .../timeline/HadoopTimelineMetricsSinkTest.java |    21 +-
 ambari-project/pom.xml                          |    52 +-
 .../docs/security/kerberos/kerberos_service.md  |    22 +-
 ambari-server/pom.xml                           |    95 +-
 .../actionmanager/ExecutionCommandWrapper.java  |    47 +-
 .../ambari/server/agent/CommandRepository.java  |    85 +
 .../ambari/server/agent/ExecutionCommand.java   |    36 +-
 .../ambari/server/agent/HeartbeatMonitor.java   |     3 +-
 .../ambari/server/agent/HeartbeatProcessor.java |    70 +-
 .../agent/stomp/dto/HostRepositories.java       |     2 +-
 .../api/handlers/BaseManagementHandler.java     |     8 -
 .../server/api/handlers/CreateHandler.java      |     4 +
 .../resources/ResourceInstanceFactoryImpl.java  |     5 +
 .../RootServiceComponentResourceDefinition.java |     9 +-
 .../server/api/services/AmbariMetaInfo.java     |     4 +-
 .../ambari/server/api/services/BaseService.java |     5 +-
 .../server/api/services/LoggingService.java     |     4 +
 ...iceComponentConfigurationRequestSwagger.java |    43 +
 ...ceComponentConfigurationResponseSwagger.java |    43 +
 ...ootServiceComponentConfigurationService.java |   226 +
 .../server/api/services/RootServiceService.java |     7 +
 .../api/services/ldap/AmbariConfiguration.java  |    46 +
 .../api/services/ldap/LdapConfigOperation.java  |    43 +
 .../services/ldap/LdapConfigurationRequest.java |    49 +
 .../services/ldap/LdapConfigurationService.java |   185 +
 .../api/services/ldap/LdapRequestInfo.java      |    61 +
 .../stackadvisor/StackAdvisorRequest.java       |    31 +
 .../commands/StackAdvisorCommand.java           |    77 +-
 .../ambari/server/checks/CheckDescription.java  |     9 +
 .../checks/DatabaseConsistencyCheckHelper.java  |     2 +-
 .../apache/ambari/server/checks/LZOCheck.java   |    80 +
 .../server/configuration/Configuration.java     |    32 +
 .../controller/ActionExecutionContext.java      |     6 +-
 .../controller/AmbariActionExecutionHelper.java |    73 +-
 .../AmbariCustomCommandExecutionHelper.java     |    37 +-
 .../server/controller/AmbariHandlerList.java    |     5 +-
 .../AmbariManagementControllerImpl.java         |    99 +-
 .../ambari/server/controller/AmbariServer.java  |     6 +-
 .../server/controller/ControllerModule.java     |     3 +
 .../controller/DeleteIdentityHandler.java       |     3 +-
 .../server/controller/KerberosHelper.java       |    21 +-
 .../server/controller/KerberosHelperImpl.java   |   169 +-
 .../controller/MaintenanceStateHelper.java      |     3 +-
 .../server/controller/RepositoryResponse.java   |    23 +-
 .../controller/ResourceProviderFactory.java     |    24 +-
 .../ambari/server/controller/RootComponent.java |    27 +
 .../ambari/server/controller/RootService.java   |    36 +
 .../controller/RootServiceResponseFactory.java  |    44 +-
 .../AbstractControllerResourceProvider.java     |     2 +
 .../internal/AbstractPropertyProvider.java      |     4 +
 .../internal/AbstractProviderModule.java        |     4 +-
 .../internal/AbstractResourceProvider.java      |     2 +-
 .../internal/ActionResourceProvider.java        |     4 +
 .../AlertDefinitionResourceProvider.java        |     4 +
 .../internal/AlertGroupResourceProvider.java    |     4 +
 .../internal/AlertResourceProvider.java         |     4 +
 .../internal/AlertTargetResourceProvider.java   |     4 +
 .../internal/ArtifactResourceProvider.java      |     4 +
 .../controller/internal/BaseProvider.java       |     6 +-
 .../BlueprintConfigurationProcessor.java        |     2 +-
 .../internal/BlueprintResourceProvider.java     |     7 +-
 .../internal/ClientConfigResourceProvider.java  |     2 +
 .../internal/ClusterResourceProvider.java       |     4 +
 .../ClusterStackVersionResourceProvider.java    |    59 +-
 ...atibleRepositoryVersionResourceProvider.java |     4 +
 .../internal/ComponentResourceProvider.java     |     4 +
 .../internal/CredentialResourceProvider.java    |     4 +
 .../internal/DefaultProviderModule.java         |    24 +-
 .../internal/GroupResourceProvider.java         |     4 +
 .../internal/HostComponentResourceProvider.java |     4 +
 .../HostKerberosIdentityResourceProvider.java   |    16 +-
 .../internal/HostResourceProvider.java          |    56 +-
 .../HostStackVersionResourceProvider.java       |     7 +-
 .../controller/internal/HostStatusHelper.java   |     2 +-
 .../internal/HttpPropertyProvider.java          |     2 +-
 .../internal/JsonHttpPropertyRequest.java       |     2 +-
 .../internal/LdapSyncEventResourceProvider.java |     2 +-
 .../internal/MemberResourceProvider.java        |     4 +
 .../QuickLinkArtifactResourceProvider.java      |     4 +
 .../RecommendationResourceProvider.java         |     4 +
 .../internal/RepositoryResourceProvider.java    |     3 +
 .../internal/RequestResourceProvider.java       |     4 +
 .../RoleAuthorizationResourceProvider.java      |     4 +
 ...eComponentConfigurationResourceProvider.java |   476 +
 .../RootServiceComponentPropertyProvider.java   |     4 +-
 .../RootServiceComponentResourceProvider.java   |     4 +-
 .../internal/ServiceResourceProvider.java       |     7 +-
 .../internal/StackAdvisorResourceProvider.java  |    13 +-
 .../internal/StackArtifactResourceProvider.java |     5 +
 .../internal/StageResourceProvider.java         |     4 +
 .../internal/TaskResourceProvider.java          |     4 +
 .../internal/ThemeArtifactResourceProvider.java |     4 +
 .../internal/UpgradeItemResourceProvider.java   |     4 +
 .../internal/UpgradeResourceProvider.java       |    59 +-
 .../internal/UserResourceProvider.java          |     4 +
 .../internal/ValidationResourceProvider.java    |     4 +
 .../VersionDefinitionResourceProvider.java      |    13 +
 .../controller/jdbc/JDBCResourceProvider.java   |     2 +-
 .../controller/jmx/JMXPropertyProvider.java     |     2 +-
 .../metrics/MetricsCollectorHAClusterState.java |     2 +-
 .../metrics/MetricsCollectorHAManager.java      |     2 +-
 .../metrics/MetricsDownsamplingMethod.java      |     2 +-
 .../metrics/MetricsPropertyProvider.java        |     2 +-
 .../metrics/MetricsReportPropertyProvider.java  |     2 +-
 .../metrics/RestMetricsPropertyProvider.java    |     2 +-
 .../ThreadPoolEnabledPropertyProvider.java      |     4 +
 .../ganglia/GangliaPropertyProvider.java        |     2 +-
 .../ganglia/GangliaReportPropertyProvider.java  |     2 +-
 .../metrics/timeline/AMSPropertyProvider.java   |     3 +
 .../timeline/AMSReportPropertyProvider.java     |     3 +
 .../ambari/server/controller/spi/Resource.java  |     3 +
 .../controller/utilities/DatabaseChecker.java   |     2 +-
 .../state/DefaultServiceCalculatedState.java    |     2 +-
 .../state/FlumeServiceCalculatedState.java      |     4 +
 .../state/HBaseServiceCalculatedState.java      |     4 +
 .../state/HDFSServiceCalculatedState.java       |     4 +
 .../state/HiveServiceCalculatedState.java       |     4 +
 .../state/OozieServiceCalculatedState.java      |     4 +
 .../state/YARNServiceCalculatedState.java       |     4 +
 .../events/AmbariConfigurationChangedEvent.java |    36 +
 .../ambari/server/events/AmbariEvent.java       |    10 +-
 .../ServiceComponentUninstalledEvent.java       |    11 +-
 .../listeners/alerts/AlertReceivedListener.java |    10 +-
 .../alerts/AlertStateChangedListener.java       |     6 +-
 .../apache/ambari/server/ldap/LdapModule.java   |    82 +
 .../ldap/domain/AmbariLdapConfigKeys.java       |    83 +
 .../ldap/domain/AmbariLdapConfiguration.java    |   203 +
 .../domain/AmbariLdapConfigurationFactory.java  |    34 +
 .../AmbariLdapConfigurationProvider.java        |   113 +
 .../ldap/service/AmbariLdapException.java       |    33 +
 .../server/ldap/service/AmbariLdapFacade.java   |   140 +
 .../server/ldap/service/AttributeDetector.java  |    41 +
 .../service/LdapAttributeDetectionService.java  |    40 +
 .../ldap/service/LdapConfigurationService.java  |    60 +
 .../service/LdapConnectionConfigService.java    |    36 +
 .../ambari/server/ldap/service/LdapFacade.java  |    58 +
 .../DefaultLdapAttributeDetectionService.java   |   200 +
 .../ads/DefaultLdapConfigurationService.java    |   213 +
 .../ads/DefaultLdapConnectionConfigService.java |   113 +
 .../ads/LdapConnectionTemplateFactory.java      |   111 +
 .../ads/detectors/AttributeDetectorFactory.java |    75 +
 .../ads/detectors/ChainedAttributeDetector.java |    73 +
 .../ads/detectors/GroupMemberAttrDetector.java  |    65 +
 .../ads/detectors/GroupNameAttrDetector.java    |    70 +
 .../ads/detectors/GroupObjectClassDetector.java |    73 +
 .../OccurrenceAndWeightBasedDetector.java       |   143 +
 .../detectors/UserGroupMemberAttrDetector.java  |    64 +
 .../ads/detectors/UserNameAttrDetector.java     |    71 +
 .../ads/detectors/UserObjectClassDetector.java  |    69 +
 .../metadata/AmbariServiceAlertDefinitions.java |    20 +-
 .../dispatchers/AmbariSNMPDispatcher.java       |    10 +-
 .../ambari/server/orm/DBAccessorImpl.java       |     8 +-
 .../server/orm/dao/AlertDefinitionDAO.java      |     7 +-
 .../ambari/server/orm/dao/AlertDispatchDAO.java |     4 +-
 .../server/orm/dao/AmbariConfigurationDAO.java  |   179 +
 .../apache/ambari/server/orm/dao/DaoUtils.java  |    13 +-
 .../server/orm/dao/KerberosKeytabDAO.java       |   110 +
 .../server/orm/dao/KerberosPrincipalDAO.java    |     7 +
 .../orm/dao/KerberosPrincipalHostDAO.java       |    40 +-
 .../orm/entities/AmbariConfigurationEntity.java |   112 +
 .../entities/AmbariConfigurationEntityPK.java   |    88 +
 .../orm/entities/KerberosKeytabEntity.java      |    86 +
 .../entities/KerberosPrincipalHostEntity.java   |    57 +-
 .../entities/KerberosPrincipalHostEntityPK.java |    19 +-
 .../orm/entities/RemoteAmbariClusterEntity.java |     2 +-
 .../server/orm/entities/RepositoryEntity.java   |    53 +-
 .../orm/entities/RepositoryVersionEntity.java   |    27 +
 .../AmbariLdapAuthenticationProvider.java       |     2 +-
 .../authorization/RoleAuthorization.java        |    95 +-
 .../security/encryption/CredentialProvider.java |     2 +-
 .../serveraction/ServerActionExecutor.java      |   147 +-
 .../kerberos/ADKerberosOperationHandler.java    |    22 +-
 .../AbstractPrepareKerberosServerAction.java    |    54 +-
 .../kerberos/CleanupServerAction.java           |    14 +-
 .../server/serveraction/kerberos/Component.java |    13 +-
 .../ConfigureAmbariIdentitiesServerAction.java  |    31 +-
 .../kerberos/CreateKeytabFilesServerAction.java |    65 +-
 .../kerberos/CreatePrincipalsServerAction.java  |    53 +-
 .../kerberos/DestroyPrincipalsServerAction.java |     3 +-
 .../kerberos/IPAKerberosOperationHandler.java   |  1067 +-
 .../kerberos/KDCKerberosOperationHandler.java   |   391 +
 .../kerberos/KerberosIdentityDataFile.java      |     2 -
 .../KerberosIdentityDataFileWriter.java         |     9 +-
 .../kerberos/KerberosOperationHandler.java      |    64 +-
 .../kerberos/KerberosServerAction.java          |    48 +-
 .../kerberos/MITKerberosOperationHandler.java   |   406 +-
 .../PrepareDisableKerberosServerAction.java     |     2 +-
 .../PrepareEnableKerberosServerAction.java      |     2 +-
 .../PrepareKerberosIdentitiesServerAction.java  |     8 +-
 .../stageutils/ResolvedKerberosKeytab.java      |   257 +
 .../upgrades/CreateAndConfigureAction.java      |   164 +
 .../upgrades/FinalizeUpgradeAction.java         |    54 +-
 .../upgrades/PreconfigureKerberosAction.java    |    48 +-
 .../ambari/server/stack/MasterHostResolver.java |     2 +-
 .../apache/ambari/server/stack/RepoUtil.java    |     1 +
 .../ambari/server/stack/ServiceDirectory.java   |    29 +
 .../ambari/server/stack/ServiceModule.java      |     8 +
 .../ambari/server/stack/StackManager.java       |     5 -
 .../ambari/server/state/ConfigHelper.java       |    28 +-
 .../ambari/server/state/RepositoryInfo.java     |    23 +-
 .../apache/ambari/server/state/ServiceImpl.java |     2 +-
 .../apache/ambari/server/state/ServiceInfo.java |    16 +-
 .../ambari/server/state/UpgradeContext.java     |     2 +-
 .../server/state/alert/AlertDefinitionHash.java |     8 +-
 .../server/state/cluster/ClusterImpl.java       |     4 +-
 .../state/repository/ClusterVersionSummary.java |     3 +
 .../state/repository/ServiceVersionSummary.java |    11 +-
 .../state/repository/VersionDefinitionXml.java  |    25 +-
 .../services/AmbariServerAlertService.java      |     4 +-
 .../state/services/MetricsRetrievalService.java |     2 +-
 .../ambari/server/state/stack/OsFamily.java     |     2 +-
 .../ambari/server/state/stack/RepoTag.java      |    34 +
 .../server/state/stack/RepositoryXml.java       |    13 +
 .../ambari/server/state/stack/UpgradePack.java  |     3 +
 .../state/stack/upgrade/ClusterGrouping.java    |     2 +
 .../stack/upgrade/CreateAndConfigureTask.java   |    57 +
 .../stack/upgrade/RepositoryVersionHelper.java  |   357 +-
 .../ambari/server/state/stack/upgrade/Task.java |     6 +-
 .../svccomphost/ServiceComponentHostImpl.java   |     4 +-
 .../ambari/server/topology/AmbariContext.java   |     3 +-
 .../ambari/server/topology/Blueprint.java       |     2 +-
 .../server/topology/BlueprintFactory.java       |     3 +-
 .../ambari/server/topology/BlueprintImpl.java   |     3 +-
 .../server/topology/BlueprintValidator.java     |     3 +-
 .../server/topology/BlueprintValidatorImpl.java |    23 +-
 .../topology/ClusterConfigurationRequest.java   |     2 +-
 .../GPLLicenseNotAcceptedException.java         |    28 +
 .../server/topology/PersistedStateImpl.java     |     2 +-
 .../validators/RequiredPasswordValidator.java   |     3 +-
 .../server/upgrade/AbstractUpgradeCatalog.java  |     8 +
 .../server/upgrade/SchemaUpgradeHelper.java     |    30 +-
 .../ambari/server/upgrade/UpgradeCatalog.java   |     6 +
 .../server/upgrade/UpgradeCatalog260.java       |   201 +-
 .../server/upgrade/UpgradeCatalog261.java       |   119 +
 .../server/upgrade/UpgradeCatalog300.java       |    47 +-
 .../apache/ambari/server/utils/RetryHelper.java |     2 +-
 .../ambari/server/utils/VersionUtils.java       |    46 +-
 .../server/view/ViewDataMigrationUtility.java   |     2 +-
 .../ambari/server/view/ViewExtractor.java       |     2 +-
 .../apache/ambari/server/view/ViewRegistry.java |     2 +-
 .../server/view/ViewSubResourceProvider.java    |     4 +
 .../server/view/persistence/DataStoreImpl.java  |     2 +-
 ambari-server/src/main/python/ambari-server.py  |     2 +
 .../python/ambari_server/serverConfiguration.py |    29 +
 .../main/python/ambari_server/serverSetup.py    |     8 +-
 .../main/python/ambari_server/serverUpgrade.py  |    18 +-
 .../resources/Ambari-DDL-AzureDB-CREATE.sql     |    31 +-
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |    24 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |    22 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |    22 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |    26 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |    22 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |    23 +-
 .../src/main/resources/META-INF/persistence.xml |     2 +
 .../ATLAS/0.1.0.2.3/package/scripts/params.py   |     2 +-
 .../ATLAS/0.7.0.3.0/package/scripts/params.py   |     2 +-
 .../DRUID/0.10.1/package/scripts/druid.py       |     3 +-
 .../DRUID/0.10.1/package/scripts/params.py      |     5 +-
 .../DRUID/0.10.1/themes/theme.json              |    26 +-
 .../FALCON/0.5.0.2.1/package/scripts/falcon.py  |    11 +-
 .../HBASE/2.0.0.3.0/service_advisor.py          |    12 +-
 .../common-services/HDFS/2.1.0.2.0/metainfo.xml |    30 -
 .../HDFS/2.1.0.2.0/package/scripts/hdfs.py      |     8 +-
 .../2.1.0.2.0/package/scripts/install_params.py |     4 -
 .../2.1.0.2.0/package/scripts/params_linux.py   |     5 -
 .../common-services/HDFS/3.0.0.3.0/metainfo.xml |    30 -
 .../HDFS/3.0.0.3.0/package/scripts/hdfs.py      |     8 +-
 .../3.0.0.3.0/package/scripts/install_params.py |     4 -
 .../3.0.0.3.0/package/scripts/params_linux.py   |     4 -
 .../HIVE/0.12.0.2.0/configuration/hive-site.xml |    40 +-
 .../HIVE/0.12.0.2.0/metainfo.xml                |     5 -
 .../package/alerts/alert_hive_thrift_port.py    |     3 +-
 .../0.12.0.2.0/package/files/startMetastore.sh  |     4 +-
 .../HIVE/0.12.0.2.0/package/scripts/hive.py     |    15 +-
 .../package/scripts/hive_server_interactive.py  |    20 +-
 .../0.12.0.2.0/package/scripts/hive_service.py  |    10 +-
 .../package/scripts/hive_service_interactive.py |     5 +-
 .../0.12.0.2.0/package/scripts/params_linux.py  |     3 +-
 .../0.12.0.2.0/package/scripts/service_check.py |     6 +-
 .../package/scripts/webhcat_service.py          |    19 +-
 .../common-services/HIVE/2.1.0.3.0/metainfo.xml |    10 -
 .../2.1.0.3.0/package/files/startMetastore.sh   |     4 +-
 .../HIVE/2.1.0.3.0/package/scripts/hive.py      |     3 +
 .../2.1.0.3.0/package/scripts/hive_service.py   |     8 +-
 .../package/scripts/hive_service_interactive.py |     5 +-
 .../2.1.0.3.0/package/scripts/params_linux.py   |    10 +-
 .../2.1.0.3.0/package/scripts/service_check.py  |     6 +-
 .../package/scripts/webhcat_service.py          |    19 +-
 .../1.10.3-10/configuration/kerberos-env.xml    |    36 +-
 .../package/scripts/kerberos_common.py          |     7 +-
 .../1.10.3-30/configuration/kerberos-env.xml    |    36 +-
 .../package/scripts/kerberos_common.py          |     7 +-
 .../LOGSEARCH/0.5.0/metainfo.xml                |     6 +-
 .../1.0.0.2.3/package/scripts/service_check.py  |     3 +-
 .../OOZIE/4.0.0.2.0/package/scripts/oozie.py    |    38 +-
 .../4.0.0.2.0/package/scripts/params_linux.py   |     5 +-
 .../OOZIE/4.2.0.2.3/metainfo.xml                |     5 -
 .../OOZIE/4.2.0.3.0/metainfo.xml                |    14 +-
 .../OOZIE/4.2.0.3.0/package/scripts/oozie.py    |    15 +-
 .../4.2.0.3.0/package/scripts/params_linux.py   |     5 +-
 .../0.5.0.2.3/configuration/kms-site.xml        |    26 -
 .../1.0.0.3.0/configuration/kms-site.xml        |    26 -
 .../scripts/alerts/alert_spark_thrift_port.py   |     8 +-
 .../SPARK/1.2.1/package/scripts/setup_spark.py  |     3 +-
 .../scripts/alerts/alert_spark2_thrift_port.py  |     8 +-
 .../SPARK2/2.0.0/package/scripts/setup_spark.py |     3 +-
 .../SQOOP/1.4.4.2.0/metainfo.xml                |     5 -
 .../1.4.4.2.0/package/scripts/params_linux.py   |     4 +-
 .../SQOOP/1.4.4.3.0/metainfo.xml                |    10 -
 .../1.4.4.3.0/package/scripts/params_linux.py   |     4 +-
 .../SUPERSET/0.15.0/themes/theme.json           |    22 +-
 .../0.4.0.2.1/package/scripts/params_linux.py   |     2 +-
 .../TEZ/0.4.0.2.1/package/scripts/tez.py        |     5 +-
 .../TEZ/0.9.0.3.0/configuration/tez-site.xml    |     4 +-
 .../0.9.0.3.0/package/scripts/params_linux.py   |     2 +-
 .../TEZ/0.9.0.3.0/package/scripts/tez.py        |     4 +
 .../configuration-mapred/mapred-site.xml        |     2 +-
 .../2.1.0.2.0/package/scripts/params_linux.py   |     8 +-
 .../YARN/2.1.0.2.0/package/scripts/yarn.py      |     3 +
 .../configuration-mapred/mapred-site.xml        |     2 +-
 .../3.0.0.3.0/package/scripts/params_linux.py   |     8 +-
 .../YARN/3.0.0.3.0/package/scripts/yarn.py      |     3 +
 .../ZEPPELIN/0.7.0/package/scripts/master.py    |    11 +-
 .../ZOOKEEPER/3.4.5/metainfo.xml                |     1 +
 .../custom_actions/scripts/install_packages.py  |    17 +-
 .../custom_actions/scripts/ru_execute_tasks.py  |     5 +-
 .../BIGTOP/0.8/services/HIVE/metainfo.xml       |     4 -
 .../BIGTOP/0.8/services/OOZIE/metainfo.xml      |     4 -
 .../2.0.6.GlusterFS/services/HIVE/metainfo.xml  |     4 -
 .../2.0.6.GlusterFS/services/OOZIE/metainfo.xml |     4 -
 .../HDP/2.0.6/properties/stack_features.json    |    20 +
 .../HDP/2.0.6/properties/stack_packages.json    |   109 +-
 .../stacks/HDP/2.0.6/role_command_order.json    |     1 +
 .../stacks/HDP/2.0.6/services/stack_advisor.py  |    35 +
 .../2.1.GlusterFS/services/HIVE/metainfo.xml    |     4 -
 .../2.1.GlusterFS/services/OOZIE/metainfo.xml   |     4 -
 .../services/HIVE/configuration/hive-site.xml   |     2 +-
 .../stacks/HDP/2.1/services/HIVE/metainfo.xml   |     5 -
 .../stacks/HDP/2.2/services/HDFS/metainfo.xml   |    35 -
 .../services/HIVE/configuration/hive-site.xml   |     2 +-
 .../stacks/HDP/2.2/services/HIVE/metainfo.xml   |    10 -
 .../stacks/HDP/2.2/services/OOZIE/metainfo.xml  |     5 -
 .../stacks/HDP/2.2/services/SQOOP/metainfo.xml  |    10 -
 .../2.2/services/TEZ/configuration/tez-site.xml |     4 +-
 .../YARN/configuration-mapred/mapred-site.xml   |     2 +-
 .../2.3.GlusterFS/services/HIVE/metainfo.xml    |     9 -
 .../2.3.GlusterFS/services/SQOOP/metainfo.xml   |     9 -
 .../main/resources/stacks/HDP/2.3/metainfo.xml  |     2 +-
 .../stacks/HDP/2.3/services/HDFS/metainfo.xml   |    30 -
 .../stacks/HDP/2.3/services/HIVE/metainfo.xml   |    10 -
 .../stacks/HDP/2.3/upgrades/config-upgrade.xml  |     4 +-
 .../HDP/2.3/upgrades/nonrolling-upgrade-2.6.xml |     1 +
 .../stacks/HDP/2.3/upgrades/upgrade-2.6.xml     |     1 +
 .../stacks/HDP/2.4/upgrades/config-upgrade.xml  |     4 +-
 .../HDP/2.4/upgrades/nonrolling-upgrade-2.6.xml |     1 +
 .../stacks/HDP/2.4/upgrades/upgrade-2.6.xml     |     1 +
 .../stacks/HDP/2.5/services/HIVE/metainfo.xml   |    10 -
 .../services/YARN/configuration/yarn-site.xml   |     4 +-
 .../stacks/HDP/2.5/services/YARN/kerberos.json  |    12 +-
 .../stacks/HDP/2.5/services/stack_advisor.py    |     2 +-
 .../stacks/HDP/2.5/upgrades/config-upgrade.xml  |    27 +-
 .../HDP/2.5/upgrades/nonrolling-upgrade-2.6.xml |    24 +-
 .../stacks/HDP/2.5/upgrades/upgrade-2.6.xml     |    46 +-
 .../resources/stacks/HDP/2.6/repos/repoinfo.xml |     2 +-
 .../stacks/HDP/2.6/services/FALCON/metainfo.xml |    26 +
 .../stacks/HDP/2.6/services/OOZIE/metainfo.xml  |    37 +
 .../configuration/spark2-log4j-properties.xml   |    56 +
 .../stacks/HDP/2.6/services/YARN/kerberos.json  |    24 +-
 .../stacks/HDP/2.6/services/stack_advisor.py    |     3 +
 .../stacks/HDP/2.6/upgrades/config-upgrade.xml  |    41 +-
 .../HDP/2.6/upgrades/nonrolling-upgrade-2.6.xml |    18 +-
 .../stacks/HDP/2.6/upgrades/upgrade-2.6.xml     |     9 +
 .../HDP/3.0/properties/stack_packages.json      |   110 +-
 .../stacks/HDP/3.0/services/HDFS/metainfo.xml   |    30 -
 .../YARN/configuration-mapred/mapred-site.xml   |     2 +-
 .../services/YARN/configuration/yarn-site.xml   |     4 +-
 .../PERF/1.0/configuration/cluster-env.xml      |    26 +
 .../resources/stacks/PERF/1.0/hdp_urlinfo.json  |    12 +
 .../1.0/hooks/before-INSTALL/scripts/hook.py    |     7 +
 .../PERF/1.0/properties/stack_packages.json     |     8 +
 .../stacks/PERF/1.0/repos/repoinfo.xml          |     1 +
 .../FAKEYARN/configuration/yarn-site.xml        |     4 +-
 .../KERBEROS/configuration/kerberos-env.xml     |    36 +-
 .../src/main/resources/stacks/PERF/1.0/vdf.xml  |    73 +
 .../resources/stacks/PERF/2.0/hdp_urlinfo.json  |    12 +
 .../stacks/PERF/2.0/repos/repoinfo.xml          |     1 +
 .../src/main/resources/stacks/PERF/2.0/vdf.xml  |    74 +
 .../src/main/resources/stacks/stack_advisor.py  |     9 +
 .../src/main/resources/upgrade-pack.xsd         |     9 +-
 .../src/main/resources/version_definition.xsd   |    23 +-
 .../ExecutionCommandWrapperTest.java            |    15 +-
 .../server/agent/TestHeartbeatHandler.java      |     2 +-
 .../commands/StackAdvisorCommandTest.java       |   212 +
 .../ambari/server/checks/LZOCheckTest.java      |   152 +
 .../server/checks/UpgradeCheckOrderTest.java    |     3 +-
 .../AmbariCustomCommandExecutionHelperTest.java |     3 +-
 .../AmbariManagementControllerImplTest.java     |     5 +-
 .../AmbariManagementControllerTest.java         |   234 +-
 .../server/controller/KerberosHelperTest.java   |    12 +-
 .../RootServiceResponseFactoryTest.java         |    27 +-
 .../ClientConfigResourceProviderTest.java       |     2 +
 ...ClusterStackVersionResourceProviderTest.java |   286 +
 ...ostKerberosIdentityResourceProviderTest.java |    12 +-
 .../internal/HostResourceProviderTest.java      |     6 +-
 .../RepositoryResourceProviderTest.java         |     6 +-
 ...ponentConfigurationResourceProviderTest.java |   393 +
 ...ootServiceComponentPropertyProviderTest.java |    15 +-
 ...ootServiceComponentResourceProviderTest.java |     9 +-
 .../StackAdvisorResourceProviderTest.java       |    97 +-
 .../internal/UpgradeResourceProviderTest.java   |    20 +-
 .../ValidationResourceProviderTest.java         |     4 +-
 .../utilities/KerberosIdentityCleanerTest.java  |    10 +-
 .../HostVersionOutOfSyncListenerTest.java       |     2 +-
 .../server/ldap/LdapModuleFunctionalTest.java   |   149 +
 .../TestAmbariLdapConfigurationFactory.java     |    29 +
 .../ldap/service/AmbariLdapFacadeTest.java      |   215 +
 ...efaultLdapAttributeDetectionServiceTest.java |   188 +
 .../DefaultLdapConfigurationServiceTest.java    |   221 +
 .../detectors/GroupMemberAttrDetectorTest.java  |   107 +
 .../metadata/AgentAlertDefinitionsTest.java     |     6 +-
 .../notifications/DispatchFactoryTest.java      |     3 +-
 .../dispatchers/AmbariSNMPDispatcherTest.java   |    23 +-
 .../server/orm/InMemoryDefaultTestModule.java   |     2 +
 .../ambari/server/orm/JdbcPropertyTest.java     |     5 +-
 .../apache/ambari/server/orm/OrmTestHelper.java |     4 +-
 .../server/orm/dao/AlertDefinitionDAOTest.java  |     7 +-
 .../orm/dao/AmbariConfigurationDAOTest.java     |   298 +
 ...uthenticationProviderForDNWithSpaceTest.java |    35 +-
 .../AmbariLdapAuthenticationProviderTest.java   |     3 +-
 .../AmbariLocalUserProviderTest.java            |     3 +-
 .../authorization/LdapServerPropertiesTest.java |     5 +-
 .../ADKerberosOperationHandlerTest.java         |   261 +-
 ...AbstractPrepareKerberosServerActionTest.java |    11 +-
 ...nfigureAmbariIdentitiesServerActionTest.java |    11 +-
 .../FinalizeKerberosServerActionTest.java       |     5 +
 .../IPAKerberosOperationHandlerTest.java        |   147 +-
 .../KDCKerberosOperationHandlerTest.java        |   168 +
 .../kerberos/KerberosIdentityDataFileTest.java  |     8 +-
 .../kerberos/KerberosOperationHandlerTest.java  |   152 +-
 .../kerberos/KerberosServerActionTest.java      |   137 +-
 .../MITKerberosOperationHandlerTest.java        |   633 +-
 .../upgrades/CreateAndConfigureActionTest.java  |   357 +
 .../PreconfigureKerberosActionTest.java         |    10 +
 .../ambari/server/stack/ServiceModuleTest.java  |    30 +
 .../server/stack/StackManagerExtensionTest.java |     6 +
 .../ambari/server/state/ConfigHelperTest.java   |    47 +
 .../state/alerts/AlertReceivedListenerTest.java |    16 +-
 .../alerts/AlertStateChangedEventTest.java      |     4 +-
 .../state/repository/VersionDefinitionTest.java |    77 +-
 .../AlertNoticeDispatchServiceTest.java         |    53 +-
 .../upgrade/RepositoryVersionHelperTest.java    |     2 +-
 .../server/topology/BlueprintImplTest.java      |    87 +-
 .../topology/BlueprintValidatorImplTest.java    |    10 +-
 .../server/upgrade/UpgradeCatalog260Test.java   |   136 +-
 .../server/upgrade/UpgradeCatalog300Test.java   |   195 +-
 .../ambari/server/utils/TestVersionUtils.java   |     4 +
 .../src/test/python/TestAmbariServer.py         |    11 +-
 .../configs/install_packages_config.json        |     1 +
 .../install_packages_repository_file.json       |     1 +
 .../custom_actions/test_ru_execute_tasks.py     |     6 +-
 .../stacks/2.0.6/HIVE/test_hive_metastore.py    |     8 +-
 .../stacks/2.0.6/HIVE/test_hive_server.py       |    18 +-
 .../2.0.6/HIVE/test_hive_service_check.py       |     2 +-
 .../stacks/2.0.6/HIVE/test_webhcat_server.py    |     4 -
 .../stacks/2.0.6/common/test_stack_advisor.py   |    59 +-
 .../stacks/2.0.6/configs/repository_file.json   |     1 +
 .../stacks/2.1/FALCON/test_falcon_server.py     |    16 +-
 .../stacks/2.1/HIVE/test_hive_metastore.py      |     9 +-
 .../python/stacks/2.1/TEZ/test_tez_client.py    |     2 +-
 .../stacks/2.2/SPARK/test_job_history_server.py |    12 +-
 .../stacks/2.2/SPARK/test_spark_client.py       |    12 +-
 .../stacks/2.2/common/test_conf_select.py       |    14 +-
 .../stacks/2.2/configs/oozie-upgrade.json       |     3 +-
 .../2.3/MAHOUT/test_mahout_service_check.py     |     4 +-
 .../2.3/SPARK/test_spark_thrift_server.py       |     6 +-
 .../HIVE/running_withMOTDmsg_andTrailingMsg.txt |    46 +
 .../stacks/2.5/HIVE/test_hive_server_int.py     |    36 +-
 .../stacks/2.5/common/test_stack_advisor.py     |     2 +-
 .../2.5/configs/ranger-admin-secured.json       |     2 -
 .../stacks/2.5/configs/ranger-kms-secured.json  |     2 -
 .../stacks/2.6/common/test_stack_advisor.py     |    11 +
 .../2.6/configs/ranger-admin-secured.json       |     2 -
 .../PreconfigureActionTest_cluster_config.json  |     4 +-
 .../test_kerberos_descriptor_ranger_kms.json    |   286 +
 .../resources/version_definition_with_tags.xml  |    86 +
 ambari-web/app/assets/test/tests.js             |     3 +
 ambari-web/app/config.js                        |     1 -
 .../app/controllers/global/update_controller.js |     2 +-
 ambari-web/app/controllers/installer.js         |    58 +-
 .../main/admin/kerberos/step1_controller.js     |    52 +-
 .../main/admin/kerberos/step2_controller.js     |     2 +-
 .../main/dashboard/config_history_controller.js |    92 +-
 .../main/host/bulk_operations_controller.js     |    14 +-
 ambari-web/app/controllers/main/service/item.js |    13 +-
 .../main/service/reassign/step3_controller.js   |     3 +
 .../main/service/reassign/step4_controller.js   |    12 +-
 .../app/controllers/wizard/step8_controller.js  |    12 +-
 .../app/mappers/components_state_mapper.js      |     1 +
 .../app/mappers/repository_version_mapper.js    |     3 +-
 ambari-web/app/mappers/stack_mapper.js          |     3 +-
 ambari-web/app/messages.js                      |    31 +-
 ambari-web/app/mixins/common/serverValidator.js |    41 +-
 .../main/host/details/actions/check_host.js     |     8 +-
 .../app/mixins/wizard/addSecurityConfigs.js     |     7 +
 .../app/models/alerts/alert_definition.js       |    18 +-
 ambari-web/app/models/client_component.js       |     1 +
 ambari-web/app/models/repository.js             |    17 +
 .../app/models/stack_version/repository.js      |     3 +-
 ambari-web/app/routes/main.js                   |     1 -
 ambari-web/app/styles/application.less          |    11 +-
 ambari-web/app/styles/hosts.less                |    89 +-
 .../app/styles/theme/bootstrap-ambari.css       |    37 +-
 ambari-web/app/styles/visualsearch.less         |   100 +
 .../config_recommendation_popup.hbs             |   102 +-
 ambari-web/app/templates/main/alerts.hbs        |    19 +-
 .../alert_definition_summary.hbs                |     2 +-
 .../templates/main/dashboard/config_history.hbs |    23 +-
 ambari-web/app/templates/main/host.hbs          |    26 +-
 .../templates/main/host/combo_search_box.hbs    |     9 +-
 .../templates/main/service/services/hdfs.hbs    |   116 +-
 .../templates/main/service/services/yarn.hbs    |   184 +-
 ambari-web/app/templates/wizard/step1.hbs       |    36 +
 ambari-web/app/utils/ajax/ajax.js               |     4 +
 ambari-web/app/views.js                         |     3 +
 ambari-web/app/views/common/controls_view.js    |     9 +-
 .../config_validation_popup.js                  |     7 +-
 ambari-web/app/views/common/search_box_view.js  |   165 +
 ambari-web/app/views/common/table_view.js       |    11 +
 .../upgrade_version_column_view.js              |     1 -
 .../app/views/main/alert_definitions_view.js    |   264 -
 .../alert_definition_summary.js                 |     2 +-
 .../app/views/main/alerts/alert_search_box.js   |   195 +
 .../main/dashboard/config_history_search_box.js |   221 +
 .../views/main/dashboard/config_history_view.js |   101 -
 .../app/views/main/host/combo_search_box.js     |    36 +-
 .../app/views/main/service/services/yarn.js     |    21 +-
 ambari-web/test/controllers/installer_test.js   |    14 +-
 .../admin/kerberos/step1_controller_test.js     |    17 -
 .../admin/kerberos/step2_controller_test.js     |     2 +-
 .../test/controllers/main/service/item_test.js  |    49 +-
 .../service/reassign/step4_controller_test.js   |     9 +-
 ambari-web/test/init_test.js                    |     8 +
 .../test/mixins/common/serverValidator_test.js  |    15 +-
 .../test/views/common/controls_view_test.js     |     2 +-
 .../test/views/common/search_box_view_test.js   |   240 +
 .../views/main/alert_definitions_view_test.js   |   152 -
 .../views/main/alerts/alert_search_box_test.js  |   168 +
 .../dashboard/config_history_search_box_test.js |   207 +
 .../main/dashboard/config_history_view_test.js  |   187 -
 .../views/main/host/combo_search_box_test.js    |    66 +-
 .../views/main/service/services/yarn_test.js    |    22 -
 .../vendor/scripts/theme/bootstrap-ambari.js    |    37 +-
 .../stacks/ODPi/2.0/services/HIVE/metainfo.xml  |    10 -
 contrib/utils/perf/deploy-gce-perf-cluster.py   |     1 +
 contrib/version-builder/version_builder.py      |    13 +-
 .../resources/ui/app/components/upload-file.js  |    38 +-
 .../files/src/main/resources/ui/bower.json      |     4 +-
 .../src/main/resources/ui/hive-web/bower.json   |     4 +-
 contrib/views/storm/pom.xml                     |   103 +-
 .../src/main/resources/images/icon-bolt.png     |   Bin 2157 -> 0 bytes
 .../src/main/resources/images/icon-spout.png    |   Bin 2620 -> 0 bytes
 .../storm/src/main/resources/images/loader.gif  |   Bin 15017 -> 0 bytes
 .../views/storm/src/main/resources/index.html   |    45 -
 .../js/backbone-paginator.min.js                |  1325 --
 .../main/resources/libs/Backbone/js/Backbone.js |  1920 --
 .../libs/Bootstrap/css/bootstrap-editable.css   |   663 -
 .../libs/Bootstrap/css/bootstrap-slider.min.css |    28 -
 .../libs/Bootstrap/css/bootstrap-switch.min.css |    22 -
 .../resources/libs/Bootstrap/css/bootstrap.css  |  5959 -----
 .../fonts/glyphicons-halflings-regular.eot      |   Bin 20127 -> 0 bytes
 .../fonts/glyphicons-halflings-regular.svg      |   288 -
 .../fonts/glyphicons-halflings-regular.ttf      |   Bin 45404 -> 0 bytes
 .../fonts/glyphicons-halflings-regular.woff     |   Bin 23424 -> 0 bytes
 .../fonts/glyphicons-halflings-regular.woff2    |   Bin 18028 -> 0 bytes
 .../resources/libs/Bootstrap/images/clear.png   |   Bin 509 -> 0 bytes
 .../resources/libs/Bootstrap/images/loading.gif |   Bin 1849 -> 0 bytes
 .../libs/Bootstrap/js/bootstrap-editable.min.js |     7 -
 .../libs/Bootstrap/js/bootstrap-notify.min.js   |     1 -
 .../libs/Bootstrap/js/bootstrap-slider.min.js   |    29 -
 .../libs/Bootstrap/js/bootstrap-switch.min.js   |    22 -
 .../libs/Bootstrap/js/bootstrap.min.js          |     7 -
 .../libs/Font-Awesome/css/font-awesome.min.css  |     4 -
 .../libs/Font-Awesome/fonts/FontAwesome.otf     |   Bin 109688 -> 0 bytes
 .../Font-Awesome/fonts/fontawesome-webfont.eot  |   Bin 70807 -> 0 bytes
 .../Font-Awesome/fonts/fontawesome-webfont.svg  |   655 -
 .../Font-Awesome/fonts/fontawesome-webfont.ttf  |   Bin 142072 -> 0 bytes
 .../Font-Awesome/fonts/fontawesome-webfont.woff |   Bin 83588 -> 0 bytes
 .../fonts/fontawesome-webfont.woff2             |   Bin 66624 -> 0 bytes
 .../resources/libs/Underscore/js/Underscore.js  |  1548 --
 .../resources/libs/bootbox/js/bootbox.min.js    |     6 -
 .../src/main/resources/libs/d3/js/d3-tip.min.js |     1 -
 .../src/main/resources/libs/d3/js/d3.min.js     |     5 -
 .../resources/libs/dagre-d3/dagre-d3.min.js     |    28 -
 .../libs/jQuery/js/jquery-2.2.3.min.js          |     4 -
 .../main/resources/libs/jsx/JSXTransformer.js   | 15201 ------------
 .../storm/src/main/resources/libs/jsx/jsx.js    |    75 -
 .../main/resources/libs/react/js/react-dom.js   |    42 -
 .../libs/react/js/react-with-addons.js          | 20775 -----------------
 .../resources/libs/require-js/js/require.min.js |    36 -
 .../main/resources/libs/require-text/js/text.js |   390 -
 .../scripts/collections/BaseCollection.js       |   197 -
 .../scripts/collections/VNimbusConfigList.js    |    52 -
 .../scripts/collections/VNimbusList.js          |    52 -
 .../scripts/collections/VSupervisorList.js      |    52 -
 .../scripts/collections/VTopologyConfigList.js  |    49 -
 .../scripts/collections/VTopologyList.js        |    52 -
 .../resources/scripts/components/BarChart.jsx   |   402 -
 .../scripts/components/Breadcrumbs.jsx          |    50 -
 .../main/resources/scripts/components/Modal.jsx |    60 -
 .../scripts/components/RadialChart.jsx          |   127 -
 .../resources/scripts/components/SearchLogs.jsx |    89 -
 .../main/resources/scripts/components/Table.jsx |   101 -
 .../scripts/components/TopologyGraph.jsx        |   199 -
 .../scripts/containers/ClusterSummary.jsx       |   122 -
 .../scripts/containers/NimbusConfigSummary.jsx  |   103 -
 .../scripts/containers/NimbusSummary.jsx        |   139 -
 .../scripts/containers/SupervisorSummary.jsx    |   155 -
 .../containers/TopologyConfiguration.jsx        |    93 -
 .../scripts/containers/TopologyDetailGraph.jsx  |    66 -
 .../scripts/containers/TopologyListing.jsx      |   188 -
 .../storm/src/main/resources/scripts/main.js    |    98 -
 .../main/resources/scripts/models/BaseModel.js  |    83 -
 .../main/resources/scripts/models/VCluster.js   |    42 -
 .../main/resources/scripts/models/VNimbus.js    |    42 -
 .../resources/scripts/models/VNimbusConfig.js   |    42 -
 .../resources/scripts/models/VSupervisor.js     |    42 -
 .../main/resources/scripts/models/VTopology.js  |    90 -
 .../resources/scripts/models/VTopologyConfig.js |    34 -
 .../scripts/modules/Table/PageableTable.jsx     |    47 -
 .../scripts/modules/Table/Pagination.jsx        |   161 -
 .../src/main/resources/scripts/router/Router.js |   123 -
 .../src/main/resources/scripts/utils/Globals.js |    30 -
 .../main/resources/scripts/utils/Overrides.js   |    30 -
 .../src/main/resources/scripts/utils/Utils.js   |   113 -
 .../scripts/views/ComponentDetailView.jsx       |   534 -
 .../main/resources/scripts/views/Dashboard.jsx  |    65 -
 .../src/main/resources/scripts/views/Footer.jsx |    48 -
 .../scripts/views/NimbusSummaryView.jsx         |    65 -
 .../resources/scripts/views/ProfilingView.jsx   |   214 -
 .../resources/scripts/views/RebalanceView.jsx   |   223 -
 .../scripts/views/SupervisorSummaryView.jsx     |    65 -
 .../scripts/views/TopologyDetailView.jsx        |  1039 -
 .../scripts/views/TopologyListingView.jsx       |    65 -
 .../storm/src/main/resources/styles/style.css   |   579 -
 .../views/storm/src/main/resources/ui/.babelrc  |    25 +
 .../src/main/resources/ui/.eslintignore.js      |     3 +
 .../storm/src/main/resources/ui/.eslintrc.js    |    58 +
 .../src/main/resources/ui/app/scripts/app.js    |    40 +
 .../ui/app/scripts/components/BarChart.jsx      |   429 +
 .../ui/app/scripts/components/Breadcrumbs.jsx   |    45 +
 .../app/scripts/components/CommonExpanded.jsx   |    30 +
 .../scripts/components/CommonNotification.jsx   |    69 +
 .../app/scripts/components/CommonPagination.jsx |    56 +
 .../components/CommonSwitchComponent.jsx        |    41 +
 .../scripts/components/CommonWindowPanel.jsx    |    99 +
 .../scripts/components/CustomToastContainer.jsx |    41 +
 .../ui/app/scripts/components/Editable.jsx      |   127 +
 .../ui/app/scripts/components/FSModel.jsx       |   149 +
 .../ui/app/scripts/components/FSReactToastr.jsx |    37 +
 .../ui/app/scripts/components/Footer.jsx        |    28 +
 .../scripts/components/LogLevelComponent.jsx    |   236 +
 .../ui/app/scripts/components/ProfilingView.jsx |   168 +
 .../ui/app/scripts/components/RadialChart.jsx   |   134 +
 .../scripts/components/RebalanceTopology.jsx    |   152 +
 .../ui/app/scripts/components/SearchLogs.jsx    |    84 +
 .../ui/app/scripts/components/TopologyGraph.jsx |   208 +
 .../ui/app/scripts/containers/BaseContainer.jsx |    50 +
 .../app/scripts/containers/ClusterSummary.jsx   |   125 +
 .../scripts/containers/ComponentDetailView.jsx  |   714 +
 .../ui/app/scripts/containers/Dashboard.jsx     |    52 +
 .../scripts/containers/NimbusConfigSummary.jsx  |   126 +
 .../ui/app/scripts/containers/NimbusSummary.jsx |   150 +
 .../scripts/containers/SupervisorSummary.jsx    |   165 +
 .../scripts/containers/TopologyDetailView.jsx   |   862 +
 .../app/scripts/containers/TopologyListing.jsx  |   222 +
 .../src/main/resources/ui/app/scripts/main.js   |    46 +
 .../ui/app/scripts/rest/TopologyREST.js         |   118 +
 .../resources/ui/app/scripts/routers/routes.jsx |    68 +
 .../resources/ui/app/scripts/utils/Constants.js |    45 +
 .../resources/ui/app/scripts/utils/Utils.js     |    51 +
 .../resources/ui/app/styles/css/bootstrap.css   |  6757 ++++++
 .../ui/app/styles/css/font-awesome.min.css      |     4 +
 .../main/resources/ui/app/styles/css/style.css  |   836 +
 .../resources/ui/app/styles/css/toastr.min.css  |     1 +
 .../ui/app/styles/fonts/fontawesome-webfont.eot |   Bin 0 -> 76518 bytes
 .../ui/app/styles/fonts/fontawesome-webfont.svg |   685 +
 .../ui/app/styles/fonts/fontawesome-webfont.ttf |   Bin 0 -> 152796 bytes
 .../app/styles/fonts/fontawesome-webfont.woff   |   Bin 0 -> 90412 bytes
 .../app/styles/fonts/fontawesome-webfont.woff2  |   Bin 0 -> 71896 bytes
 .../fonts/glyphicons-halflings-regular.eot      |   Bin 0 -> 20127 bytes
 .../fonts/glyphicons-halflings-regular.svg      |   288 +
 .../fonts/glyphicons-halflings-regular.ttf      |   Bin 0 -> 45404 bytes
 .../fonts/glyphicons-halflings-regular.woff     |   Bin 0 -> 23424 bytes
 .../fonts/glyphicons-halflings-regular.woff2    |   Bin 0 -> 18028 bytes
 .../resources/ui/app/styles/img/icon-bolt.png   |   Bin 0 -> 2157 bytes
 .../resources/ui/app/styles/img/icon-spout.png  |   Bin 0 -> 2620 bytes
 .../main/resources/ui/app/styles/img/loader.gif |   Bin 0 -> 15017 bytes
 .../resources/ui/config/webpack.config.base.js  |   101 +
 .../ui/config/webpack.config.development.js     |    64 +
 .../ui/config/webpack.config.production.js      |   131 +
 .../storm/src/main/resources/ui/dev-server.js   |   101 +
 .../storm/src/main/resources/ui/index.html      |    47 +
 .../storm/src/main/resources/ui/package.json    |   110 +
 .../apache/ambari/view/utils/hdfs/HdfsApi.java  |    16 +-
 .../apache/ambari/view/utils/hdfs/HdfsUtil.java |    17 +-
 .../ui/app/domain/workflow-importer.js          |     3 +-
 docs/pom.xml                                    |    22 +-
 pom.xml                                         |     7 +-
 1019 files changed, 52897 insertions(+), 69721 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-agent/src/main/python/ambari_agent/HostInfo.py
----------------------------------------------------------------------
diff --cc ambari-agent/src/main/python/ambari_agent/HostInfo.py
index e3c70d4,4a752fc..a11f188
--- a/ambari-agent/src/main/python/ambari_agent/HostInfo.py
+++ b/ambari-agent/src/main/python/ambari_agent/HostInfo.py
@@@ -313,33 -314,35 +315,33 @@@ class HostInfoLinux(HostInfo)
        logger.exception('Unable to get information about JCE')
        return None
  
-   def register(self, dict, runExpensiveChecks=False, checkJavaProcs=False):
 -  def register(self, metrics, componentsMapped=True, commandsInProgress=True):
 -    """ Return various details about the host
 -    componentsMapped: indicates if any components are mapped to this host
 -    commandsInProgress: indicates if any commands are in progress
 -    """
++  def register(self, metrics, runExpensiveChecks=False, checkJavaProcs=False):
 +    """ Return various details about the host"""
  
-     dict['hostHealth'] = {}
+     metrics['hostHealth'] = {}
  
 -    java = []
 -    self.javaProcs(java)
 -    metrics['hostHealth']['activeJavaProcs'] = java
 +    if checkJavaProcs:
 +      java = []
 +      self.javaProcs(java)
-       dict['hostHealth']['activeJavaProcs'] = java
++      metrics['hostHealth']['activeJavaProcs'] = java
  
      liveSvcs = []
      self.checkLiveServices(self.DEFAULT_LIVE_SERVICES, liveSvcs)
-     dict['hostHealth']['liveServices'] = liveSvcs
+     metrics['hostHealth']['liveServices'] = liveSvcs
  
-     dict['umask'] = str(self.getUMask())
+     metrics['umask'] = str(self.getUMask())
  
-     dict['transparentHugePage'] = self.getTransparentHugePage()
-     dict['firewallRunning'] = self.checkFirewall()
-     dict['firewallName'] = self.getFirewallName()
-     dict['reverseLookup'] = self.checkReverseLookup()
-     dict['hasUnlimitedJcePolicy'] = self.checkUnlimitedJce()
+     metrics['transparentHugePage'] = self.getTransparentHugePage()
+     metrics['firewallRunning'] = self.checkFirewall()
+     metrics['firewallName'] = self.getFirewallName()
+     metrics['reverseLookup'] = self.checkReverseLookup()
+     metrics['hasUnlimitedJcePolicy'] = self.checkUnlimitedJce()
      # If commands are in progress or components are already mapped to this host
      # Then do not perform certain expensive host checks
 -    if componentsMapped or commandsInProgress:
 +    if not runExpensiveChecks:
-       dict['alternatives'] = []
-       dict['stackFoldersAndFiles'] = []
-       dict['existingUsers'] = []
+       metrics['alternatives'] = []
+       metrics['stackFoldersAndFiles'] = []
+       metrics['existingUsers'] = []
  
      else:
        etcs = []
@@@ -433,10 -436,12 +435,10 @@@ class HostInfoWindows(HostInfo)
      code, out, err = run_powershell_script(self.SERVICE_STATUS_CMD.format(serivce_name))
      return out, err, code
  
-   def register(self, dict, runExpensiveChecks=False):
 -  def register(self, metrics, componentsMapped=True, commandsInProgress=True):
++  def register(self, metrics, runExpensiveChecks=False):
      """ Return various details about the host
 -    componentsMapped: indicates if any components are mapped to this host
 -    commandsInProgress: indicates if any commands are in progress
      """
-     dict['hostHealth'] = {}
+     metrics['hostHealth'] = {}
  
      java = []
      self.javaProcs(java)
@@@ -444,18 -449,19 +446,18 @@@
  
      liveSvcs = []
      self.checkLiveServices(self.DEFAULT_LIVE_SERVICES, liveSvcs)
-     dict['hostHealth']['liveServices'] = liveSvcs
+     metrics['hostHealth']['liveServices'] = liveSvcs
  
-     dict['umask'] = str(self.getUMask())
+     metrics['umask'] = str(self.getUMask())
  
-     dict['firewallRunning'] = self.checkFirewall()
-     dict['firewallName'] = self.getFirewallName()
-     dict['reverseLookup'] = self.checkReverseLookup()
+     metrics['firewallRunning'] = self.checkFirewall()
+     metrics['firewallName'] = self.getFirewallName()
+     metrics['reverseLookup'] = self.checkReverseLookup()
 -    # If commands are in progress or components are already mapped to this host
 -    # Then do not perform certain expensive host checks
 -    if componentsMapped or commandsInProgress:
 +
 +    if not runExpensiveChecks:
-       dict['alternatives'] = []
-       dict['stackFoldersAndFiles'] = []
-       dict['existingUsers'] = []
+       metrics['alternatives'] = []
+       metrics['stackFoldersAndFiles'] = []
+       metrics['existingUsers'] = []
      else:
        existingUsers = []
        self.checkUsers(self.DEFAULT_USERS, existingUsers)

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
----------------------------------------------------------------------
diff --cc ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
index eb658be,5c0305e..35aff82
--- a/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
@@@ -484,8 -462,8 +484,8 @@@ class BaseAlert(object)
  
        # get the host for dfs.namenode.http-address.c1ha.nn1 and see if it's
        # this host
 -      value = self._get_configuration_value(key)
 +      value = self._get_configuration_value(configurations, key)
-       if value is not None and (self.host_name in value or self.public_host_name in value):
+       if value is not None and (self.host_name.lower() in value.lower() or self.public_host_name.lower() in value.lower()):
          return AlertUri(uri=value, is_ssl_enabled=is_ssl_enabled)
  
      return None

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-common/src/main/python/resource_management/libraries/functions/conf_select.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-common/src/main/python/resource_management/libraries/functions/copy_tarball.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-common/src/main/python/resource_management/libraries/functions/package_conditions.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-common/src/main/python/resource_management/libraries/functions/stack_select.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-common/src/main/python/resource_management/libraries/script/script.py
----------------------------------------------------------------------
diff --cc ambari-common/src/main/python/resource_management/libraries/script/script.py
index 97e7e50,88e5336..2c45b16
--- a/ambari-common/src/main/python/resource_management/libraries/script/script.py
+++ b/ambari-common/src/main/python/resource_management/libraries/script/script.py
@@@ -775,10 -776,9 +776,10 @@@ class Script(object)
      if self.available_packages_in_repos:
        return self.available_packages_in_repos
  
 -    pkg_provider = get_provider("Package")   
 +
 +    pkg_provider = get_provider("Package")
      try:
-       self.available_packages_in_repos = pkg_provider.get_available_packages_in_repos(self.get_config()['repositoryFile']['repositories'])
+       self.available_packages_in_repos = pkg_provider.get_available_packages_in_repos(CommandRepository(self.get_config()['repositoryFile']))
      except Exception as err:
        Logger.exception("Unable to load available packages")
        self.available_packages_in_repos = []

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-project/pom.xml
----------------------------------------------------------------------
diff --cc ambari-project/pom.xml
index d9ad50b,f6e3bc7..a141c4f
--- a/ambari-project/pom.xml
+++ b/ambari-project/pom.xml
@@@ -30,7 -30,8 +30,8 @@@
      <solr.version>5.5.2</solr.version>
      <ambari.dir>${project.parent.basedir}</ambari.dir>
      <powermock.version>1.6.3</powermock.version>
 -    <jetty.version>8.1.19.v20160209</jetty.version>
 +    <jetty.version>9.4.2.v20170220</jetty.version>
+     <ldap-api.version>1.0.0</ldap-api.version>
      <checkstyle.version>6.19</checkstyle.version> <!-- last version that does not require Java 8 -->
      <swagger.version>1.5.10</swagger.version>
      <swagger.maven.plugin.version>3.1.4</swagger.maven.plugin.version>

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
index 1bf67c3,191e86c..7e8e61f
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
@@@ -20,8 -20,8 +20,7 @@@ package org.apache.ambari.server.action
  import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
  import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
  import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
- import static org.apache.ambari.server.stack.StackManager.DEFAULT_HOOKS_FOLDER;
  
 -import java.util.HashMap;
  import java.util.Map;
  import java.util.TreeMap;
  
@@@ -47,6 -52,8 +51,7 @@@ import org.apache.ambari.server.state.S
  import org.apache.ambari.server.state.UpgradeContext;
  import org.apache.ambari.server.state.UpgradeContext.UpgradeSummary;
  import org.apache.ambari.server.state.UpgradeContextFactory;
+ import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper;
 -import org.apache.commons.collections.MapUtils;
  import org.apache.commons.lang.StringUtils;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java
index aea8ff5,449d2d5..7e0f269
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/CommandRepository.java
@@@ -47,9 -45,23 +49,24 @@@ public class CommandRepository 
    private long m_repoVersionId;
  
    @SerializedName("stackName")
 +  @JsonProperty("stackName")
    private String m_stackName;
  
+   @SerializedName("repoFileName")
+   private String m_repoFileName;
+ 
+   @SerializedName("feature")
+   private final CommandRepositoryFeature feature = new CommandRepositoryFeature();
+ 
+   /**
+    * Provides {@link CommandRepository} feature
+    *
+    * @return {@link CommandRepositoryFeature}
+    */
+   public CommandRepositoryFeature getFeature(){
+     return feature;
+   }
+ 
    /**
     * {@code true} if Ambari believes that this repository has reported back it's
     * version after distribution.

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
index 466b24c,83d2c98..fa69727
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
@@@ -223,18 -227,18 +227,17 @@@ public class HeartbeatProcessor extend
     * {@link AlertEvent}s for each one. If there is a problem looking up the
     * cluster, then alerts will not be processed.
     *
-    * @param heartbeat
-    *          the heartbeat to process.
+    * @param heartbeat the heartbeat to process.
     */
    protected void processAlerts(HeartBeat heartbeat) {
 -    if (heartbeat == null) {
 -      return;
 +    if (heartbeat != null) {
 +      processAlerts(heartbeat.getHostname(), heartbeat.getAlerts());
      }
 +  }
  
 -    String hostname = heartbeat.getHostname();
 -
 -    if (null != heartbeat.getAlerts()) {
 -      AlertEvent event = new AlertReceivedEvent(heartbeat.getAlerts());
 -      for (Alert alert : event.getAlerts()) {
 +  public void processAlerts(String hostname, List<Alert> alerts) {
 +    if (alerts != null && !alerts.isEmpty()) {
 +      for (Alert alert : alerts) {
          if (alert.getHostName() == null) {
            alert.setHostName(hostname);
          }
@@@ -307,16 -353,16 +311,17 @@@
  
    /**
     * Process reports of tasks executed on agents
+    *
     * @param heartbeat heartbeat to process
-    * @param now cached current time
+    * @param now       cached current time
     * @throws AmbariException
     */
 -  protected void processCommandReports(
 -      HeartBeat heartbeat, long now)
 +  protected void processCommandReports(HeartBeat heartbeat, long now) throws AmbariException {
 +    processCommandReports(heartbeat.getReports(), heartbeat.getHostname(), now);
 +  }
 +
 +  protected void processCommandReports(List<CommandReport> reports, String hostName, Long now)
        throws AmbariException {
 -    String hostname = heartbeat.getHostname();
 -    List<CommandReport> reports = heartbeat.getReports();
  
      // Cache HostRoleCommand entities because we will need them few times
      List<Long> taskIds = new ArrayList<>();
@@@ -402,9 -463,11 +414,11 @@@
            }
          } else if (CHECK_KEYTABS.equalsIgnoreCase(customCommand)) {
            ListKeytabsStructuredOut structuredOut = gson.fromJson(report.getStructuredOut(), ListKeytabsStructuredOut.class);
-           for (MissingKeytab each : structuredOut.missingKeytabs){
-             LOG.info("Missing keytab: {} on host: {} principal: {}", each.keytabFilePath, hostName, each.principal);
-             kerberosPrincipalHostDAO.remove(each.principal, host.getHostId());
+           for (MissingKeytab each : structuredOut.missingKeytabs) {
 -            LOG.info("Missing principal: {} for keytab: {} on host: {}", each.principal, each.keytabFilePath, hostname);
++            LOG.info("Missing principal: {} for keytab: {} on host: {}", each.principal, each.keytabFilePath, hostName);
+             KerberosPrincipalHostEntity kphe = kerberosPrincipalHostDAO.find(each.principal, host.getHostId(), each.keytabFilePath);
+             kphe.setDistributed(false);
+             kerberosPrincipalHostDAO.merge(kphe);
            }
          }
        }

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostRepositories.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostRepositories.java
index a076c66,0000000..37d1146
mode 100644,000000..100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostRepositories.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/stomp/dto/HostRepositories.java
@@@ -1,58 -1,0 +1,58 @@@
 +/**
 + * 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
 + * <p/>
 + * http://www.apache.org/licenses/LICENSE-2.0
 + * <p/>
 + * 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.
 + */
 +
 +
 +package org.apache.ambari.server.agent.stomp.dto;
 +
 +import java.util.Map;
 +
 +import org.apache.ambari.server.agent.CommandRepository;
 +
 +import com.fasterxml.jackson.annotation.JsonInclude;
 +import com.fasterxml.jackson.annotation.JsonProperty;
 +
- @JsonInclude(JsonInclude.Include.NON_EMPTY)
++@JsonInclude(JsonInclude.Include.NON_NULL)
 +public class HostRepositories {
 +
 +  @JsonProperty("commandRepos")
 +  private Map<Long, CommandRepository> repositories;
 +
 +  @JsonProperty("componentRepos")
 +  private Map<String, Long> componentRepos;
 +
 +  public HostRepositories(Map<Long, CommandRepository> repositories, Map<String, Long> componentRepos) {
 +    this.repositories = repositories;
 +    this.componentRepos = componentRepos;
 +  }
 +
 +  public Map<Long, CommandRepository> getRepositories() {
 +    return repositories;
 +  }
 +
 +  public void setRepositories(Map<Long, CommandRepository> repositories) {
 +    this.repositories = repositories;
 +  }
 +
 +  public Map<String, Long> getComponentRepos() {
 +    return componentRepos;
 +  }
 +
 +  public void setComponentRepos(Map<String, Long> componentRepos) {
 +    this.componentRepos = componentRepos;
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index 49679b4,b1eba8f..c69dceb
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@@ -45,9 -42,8 +45,9 @@@ import org.apache.ambari.annotations.Ex
  import org.apache.ambari.server.AmbariException;
  import org.apache.ambari.server.ParentObjectNotFoundException;
  import org.apache.ambari.server.StackAccessException;
 +import org.apache.ambari.server.agent.CommandRepository;
  import org.apache.ambari.server.configuration.Configuration;
- import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
+ import org.apache.ambari.server.controller.RootService;
  import org.apache.ambari.server.controller.utilities.PropertyHelper;
  import org.apache.ambari.server.customactions.ActionDefinition;
  import org.apache.ambari.server.customactions.ActionDefinitionManager;

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --cc ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index 7a98b7c,c4df0b1..e094fa7
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@@ -67,9 -68,9 +68,8 @@@ import org.apache.ambari.server.configu
  import org.apache.ambari.server.controller.internal.RequestOperationLevel;
  import org.apache.ambari.server.controller.internal.RequestResourceFilter;
  import org.apache.ambari.server.controller.spi.Resource;
 -import org.apache.ambari.server.controller.spi.SystemException;
  import org.apache.ambari.server.metadata.ActionMetadata;
  import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
- import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
  import org.apache.ambari.server.state.Cluster;
  import org.apache.ambari.server.state.Clusters;
  import org.apache.ambari.server.state.CommandScriptDefinition;

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
----------------------------------------------------------------------


[44/50] [abbrv] ambari git commit: AMBARI-22550. Service install/start failure due to wrong version directory

Posted by ao...@apache.org.
AMBARI-22550. Service install/start failure due to wrong version directory


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/19e6518d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/19e6518d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/19e6518d

Branch: refs/heads/branch-3.0-perf
Commit: 19e6518d42170a33ca2e0161ec2d3abb5190f976
Parents: ff08592
Author: Doroszlai, Attila <ad...@hortonworks.com>
Authored: Wed Nov 29 19:02:32 2017 +0100
Committer: Doroszlai, Attila <ad...@hortonworks.com>
Committed: Thu Nov 30 09:02:46 2017 +0100

----------------------------------------------------------------------
 .../actionmanager/ExecutionCommandWrapper.java       |  5 +++++
 .../actionmanager/ExecutionCommandWrapperTest.java   | 15 +++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/19e6518d/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
index 7b693cd..191e86c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
@@ -297,7 +297,12 @@ public class ExecutionCommandWrapper {
       if (null != repositoryVersion) {
         // only set the version if it's not set and this is NOT an install
         // command
+        // Some stack scripts use version for path purposes.  Sending unresolved version first (for
+        // blueprints) and then resolved one would result in various issues: duplicate directories
+        // (/hdp/apps/2.6.3.0 + /hdp/apps/2.6.3.0-235), parent directory not found, and file not
+        // found, etc.  Hence requiring repositoryVersion to be resolved.
         if (!commandParams.containsKey(VERSION)
+          && repositoryVersion.isResolved()
           && executionCommand.getRoleCommand() != RoleCommand.INSTALL) {
           commandParams.put(VERSION, repositoryVersion.getVersion());
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/19e6518d/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
index fb84df5..f12c701 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
@@ -312,8 +312,7 @@ public class ExecutionCommandWrapperTest {
     commandParams = processedExecutionCommand.getCommandParams();
     Assert.assertFalse(commandParams.containsKey(KeyNames.VERSION));
 
-    // now try with a START command which should populate the version even
-    // though the state is INSTALLING
+    // now try with a START command, but still unresolved
     executionCommand = new ExecutionCommand();
     commandParams = new HashMap<>();
 
@@ -334,6 +333,17 @@ public class ExecutionCommandWrapperTest {
 
     processedExecutionCommand = execCommWrap.getExecutionCommand();
     commandParams = processedExecutionCommand.getCommandParams();
+    Assert.assertFalse(commandParams.containsKey(KeyNames.VERSION));
+
+    // now that the repositoryVersion is resolved, it should populate the version even
+    // though the state is INSTALLING
+    repositoryVersion.setResolved(true);
+    ormTestHelper.repositoryVersionDAO.merge(repositoryVersion);
+    execCommWrap = new ExecutionCommandWrapper(json);
+    injector.injectMembers(execCommWrap);
+
+    processedExecutionCommand = execCommWrap.getExecutionCommand();
+    commandParams = processedExecutionCommand.getCommandParams();
     Assert.assertEquals("0.1-0000", commandParams.get(KeyNames.VERSION));
     }
 
@@ -346,6 +356,7 @@ public class ExecutionCommandWrapperTest {
 
     StackId stackId = cluster.getDesiredStackVersion();
     RepositoryVersionEntity repositoryVersion = ormTestHelper.getOrCreateRepositoryVersion(stackId, "0.1-0000");
+    repositoryVersion.setResolved(true); // has build number
     Service service = cluster.getService("HDFS");
     service.setDesiredRepositoryVersion(repositoryVersion);
 


[35/50] [abbrv] ambari git commit: AMBARI-22480. Validate blueprint does not allow lzo enable without setup with license agreement. (mpapirkovskyy)

Posted by ao...@apache.org.
AMBARI-22480. Validate blueprint does not allow lzo enable without setup with license agreement. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9bbc0ef7
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9bbc0ef7
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9bbc0ef7

Branch: refs/heads/branch-3.0-perf
Commit: 9bbc0ef720bc91ff39701955984bb9635d811c59
Parents: 41853a1
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Wed Nov 29 16:55:34 2017 +0200
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Wed Nov 29 18:30:08 2017 +0200

----------------------------------------------------------------------
 .../internal/BlueprintResourceProvider.java     |  3 +-
 .../ambari/server/topology/Blueprint.java       |  2 +-
 .../ambari/server/topology/BlueprintImpl.java   |  2 +-
 .../server/topology/BlueprintValidator.java     |  2 +-
 .../server/topology/BlueprintValidatorImpl.java | 21 +++++-
 .../server/topology/BlueprintImplTest.java      | 69 ++++++++++++++++++--
 .../topology/BlueprintValidatorImplTest.java    | 10 ++-
 7 files changed, 95 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
index 67f5448..8f4d62e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
@@ -56,6 +56,7 @@ import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.StackInfo;
 import org.apache.ambari.server.topology.Blueprint;
 import org.apache.ambari.server.topology.BlueprintFactory;
+import org.apache.ambari.server.topology.GPLLicenseNotAcceptedException;
 import org.apache.ambari.server.topology.InvalidTopologyException;
 import org.apache.ambari.server.topology.SecurityConfiguration;
 import org.apache.ambari.server.topology.SecurityConfigurationFactory;
@@ -519,7 +520,7 @@ public class BlueprintResourceProvider extends AbstractControllerResourceProvide
 
         try {
           blueprint.validateRequiredProperties();
-        } catch (InvalidTopologyException e) {
+        } catch (InvalidTopologyException | GPLLicenseNotAcceptedException e) {
           throw new IllegalArgumentException("Blueprint configuration validation failed: " + e.getMessage(), e);
         }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
index 779a02d..6ed38f8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
@@ -152,7 +152,7 @@ public interface Blueprint {
    *
    * @throws InvalidTopologyException if the blueprint doesn't contain all required properties
    */
-  void validateRequiredProperties() throws InvalidTopologyException;
+  void validateRequiredProperties() throws InvalidTopologyException, GPLLicenseNotAcceptedException;
 
   /**
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
index 8c83ed6..6801e33 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
@@ -353,7 +353,7 @@ public class BlueprintImpl implements Blueprint {
    * @throws InvalidTopologyException if the blueprint configuration is invalid
    */
   @Override
-  public void validateRequiredProperties() throws InvalidTopologyException {
+  public void validateRequiredProperties() throws InvalidTopologyException, GPLLicenseNotAcceptedException {
     validator.validateRequiredProperties();
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
index be194df..156fe8c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidator.java
@@ -37,5 +37,5 @@ public interface BlueprintValidator {
    *
    * @throws InvalidTopologyException if required properties are not set in blueprint
    */
-  void validateRequiredProperties() throws InvalidTopologyException;
+  void validateRequiredProperties() throws InvalidTopologyException, GPLLicenseNotAcceptedException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
index 1a43b85..87b5936 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintValidatorImpl.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.controller.internal.Stack;
 import org.apache.ambari.server.state.AutoDeployInfo;
 import org.apache.ambari.server.state.DependencyConditionInfo;
@@ -35,15 +36,24 @@ import org.apache.ambari.server.utils.VersionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.inject.Inject;
+
 /**
  * Default blueprint validator.
  */
+@StaticallyInject
 public class BlueprintValidatorImpl implements BlueprintValidator {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintValidatorImpl.class);
   private final Blueprint blueprint;
   private final Stack stack;
 
+  public static final String LZO_CODEC_CLASS_PROPERTY_NAME = "io.compression.codec.lzo.class";
+  public static final String LZO_CODEC_CLASS = "com.hadoop.compression.lzo.LzoCodec";
+
+  @Inject
+  private static org.apache.ambari.server.configuration.Configuration configuration;
+
   public BlueprintValidatorImpl(Blueprint blueprint) {
     this.blueprint = blueprint;
     this.stack = blueprint.getStack();
@@ -84,13 +94,17 @@ public class BlueprintValidatorImpl implements BlueprintValidator {
   }
 
   @Override
-  public void validateRequiredProperties() throws InvalidTopologyException {
+  public void validateRequiredProperties() throws InvalidTopologyException, GPLLicenseNotAcceptedException {
 
     // we don't want to include default stack properties so we can't just use hostGroup full properties
     Map<String, Map<String, String>> clusterConfigurations = blueprint.getConfiguration().getProperties();
 
     // we need to have real passwords, not references
     if (clusterConfigurations != null) {
+
+      // need to reject blueprints that have LZO enabled if the Ambari Server hasn't been configured for it
+      boolean gplEnabled = configuration.getGplLicenseAccepted();
+
       StringBuilder errorMessage = new StringBuilder();
       boolean containsSecretReferences = false;
       for (Map.Entry<String, Map<String, String>> configEntry : clusterConfigurations.entrySet()) {
@@ -100,6 +114,11 @@ public class BlueprintValidatorImpl implements BlueprintValidator {
             String propertyName = propertyEntry.getKey();
             String propertyValue = propertyEntry.getValue();
             if (propertyValue != null) {
+              if (!gplEnabled && configType.equals("core-site") && propertyName.equals(LZO_CODEC_CLASS_PROPERTY_NAME)
+                  && propertyValue.contains(LZO_CODEC_CLASS)) {
+                throw new GPLLicenseNotAcceptedException("Your Ambari server has not been configured to download LZO GPL software. " +
+                    "Please refer to documentation to configure Ambari before proceeding.");
+              }
               if (SecretReference.isSecret(propertyValue)) {
                 errorMessage.append("  Config:" + configType + " Property:" + propertyName + "\n");
                 containsSecretReferences = true;

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
index 6ac74a3..6d3179e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplTest.java
@@ -21,11 +21,13 @@ package org.apache.ambari.server.topology;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.mock;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -106,13 +108,14 @@ public class BlueprintImplTest {
 
   @Test
   public void testValidateConfigurations__basic_positive() throws Exception {
+    org.apache.ambari.server.configuration.Configuration serverConfig = setupConfigurationWithGPLLicense(true);
     expect(group1.getCardinality()).andReturn("1").atLeastOnce();
     expect(group1.getComponents()).andReturn(Arrays.asList(new Component("c1"), new Component("c2"))).atLeastOnce();
     expect(group2.getCardinality()).andReturn("1").atLeastOnce();
     expect(group2.getComponents()).andReturn(Arrays.asList(new Component("c1"), new Component("c3"))).atLeastOnce();
     expect(group2.getConfiguration()).andReturn(EMPTY_CONFIGURATION).atLeastOnce();
 
-    replay(stack, group1, group2);
+    replay(stack, group1, group2, serverConfig);
 
     Map<String, String> category2Props = new HashMap<>();
     properties.put("category2", category2Props);
@@ -123,7 +126,7 @@ public class BlueprintImplTest {
     blueprint.validateRequiredProperties();
     BlueprintEntity entity = blueprint.toEntity();
 
-    verify(stack, group1, group2);
+    verify(stack, group1, group2, serverConfig);
     assertTrue(entity.getSecurityType() == SecurityType.KERBEROS);
     assertTrue(entity.getSecurityDescriptorReference().equals("testRef"));
   }
@@ -134,6 +137,8 @@ public class BlueprintImplTest {
     Map<String, String> group2Category2Props = new HashMap<>();
     group2Props.put("category2", group2Category2Props);
     group2Category2Props.put("prop2", "val");
+
+    org.apache.ambari.server.configuration.Configuration serverConfig = setupConfigurationWithGPLLicense(true);
     // set config for group2 which contains a required property
     Configuration group2Configuration = new Configuration(group2Props, EMPTY_ATTRIBUTES, configuration);
     expect(group2.getConfiguration()).andReturn(group2Configuration).atLeastOnce();
@@ -155,11 +160,11 @@ public class BlueprintImplTest {
     properties.put("hadoop-env", hadoopProps);
     hadoopProps.put("dfs_ha_initial_namenode_active", "%HOSTGROUP:group1%");
     hadoopProps.put("dfs_ha_initial_namenode_standby", "%HOSTGROUP:group2%");
-    replay(stack, group1, group2);
+    replay(stack, group1, group2, serverConfig);
     Blueprint blueprint = new BlueprintImpl("test", hostGroups, stack, configuration, null);
     blueprint.validateRequiredProperties();
     BlueprintEntity entity = blueprint.toEntity();
-    verify(stack, group1, group2);
+    verify(stack, group1, group2, serverConfig);
     assertTrue(entity.getSecurityType() == SecurityType.NONE);
     assertTrue(entity.getSecurityDescriptorReference() == null);
   }
@@ -277,17 +282,55 @@ public class BlueprintImplTest {
     verify(stack, group1, group2);
   }
   @Test(expected = InvalidTopologyException.class)
-  public void testValidateConfigurations__secretReference() throws InvalidTopologyException {
+  public void testValidateConfigurations__secretReference() throws InvalidTopologyException,
+      GPLLicenseNotAcceptedException, NoSuchFieldException, IllegalAccessException {
     Map<String, Map<String, String>> group2Props = new HashMap<>();
     Map<String, String> group2Category2Props = new HashMap<>();
+
+    org.apache.ambari.server.configuration.Configuration serverConfig = setupConfigurationWithGPLLicense(true);
     group2Props.put("category2", group2Category2Props);
     group2Category2Props.put("prop2", "val");
     hdfsProps.put("secret", "SECRET:hdfs-site:1:test");
-    replay(stack, group1, group2);
+    replay(stack, group1, group2, serverConfig);
 
     Blueprint blueprint = new BlueprintImpl("test", hostGroups, stack, configuration, null);
     blueprint.validateRequiredProperties();
-    verify(stack, group1, group2);
+    verify(stack, group1, group2, serverConfig);
+  }
+
+  @Test(expected = GPLLicenseNotAcceptedException.class)
+  public void testValidateConfigurations__gplIsNotAllowed() throws InvalidTopologyException,
+      GPLLicenseNotAcceptedException, NoSuchFieldException, IllegalAccessException {
+    Map<String, Map<String, String>> lzoProperties = new HashMap<>();
+    lzoProperties.put("core-site", new HashMap<String, String>(){{
+      put(BlueprintValidatorImpl.LZO_CODEC_CLASS_PROPERTY_NAME, BlueprintValidatorImpl.LZO_CODEC_CLASS);
+    }});
+    Configuration lzoUsageConfiguration = new Configuration(lzoProperties, EMPTY_ATTRIBUTES, EMPTY_CONFIGURATION);
+
+    org.apache.ambari.server.configuration.Configuration serverConfig = setupConfigurationWithGPLLicense(false);
+    replay(stack, group1, group2, serverConfig);
+
+    Blueprint blueprint = new BlueprintImpl("test", hostGroups, stack, lzoUsageConfiguration, null);
+    blueprint.validateRequiredProperties();
+    verify(stack, group1, group2, serverConfig);
+  }
+
+  @Test
+  public void testValidateConfigurations__gplISAllowed() throws InvalidTopologyException,
+      GPLLicenseNotAcceptedException, NoSuchFieldException, IllegalAccessException {
+    Map<String, Map<String, String>> lzoProperties = new HashMap<>();
+    lzoProperties.put("core-site", new HashMap<String, String>(){{
+      put(BlueprintValidatorImpl.LZO_CODEC_CLASS_PROPERTY_NAME, BlueprintValidatorImpl.LZO_CODEC_CLASS);
+    }});
+    Configuration lzoUsageConfiguration = new Configuration(lzoProperties, EMPTY_ATTRIBUTES, EMPTY_CONFIGURATION);
+
+    org.apache.ambari.server.configuration.Configuration serverConfig = setupConfigurationWithGPLLicense(true);
+    expect(group2.getConfiguration()).andReturn(EMPTY_CONFIGURATION).atLeastOnce();
+    replay(stack, group1, group2, serverConfig);
+
+    Blueprint blueprint = new BlueprintImpl("test", hostGroups, stack, lzoUsageConfiguration, null);
+    blueprint.validateRequiredProperties();
+    verify(stack, group1, group2, serverConfig);
   }
 
   @Test
@@ -314,6 +357,18 @@ public class BlueprintImplTest {
     verify(stack, setting);
   }
 
+  public static org.apache.ambari.server.configuration.Configuration setupConfigurationWithGPLLicense(boolean isGPLAllowed)
+      throws NoSuchFieldException, IllegalAccessException {
+    org.apache.ambari.server.configuration.Configuration serverConfig =
+        mock(org.apache.ambari.server.configuration.Configuration.class);
+    expect(serverConfig.getGplLicenseAccepted()).andReturn(isGPLAllowed).atLeastOnce();
+
+    Field field = BlueprintValidatorImpl.class.getDeclaredField("configuration");
+    field.setAccessible(true);
+    field.set(null, serverConfig);
+    return serverConfig;
+  }
+
   //todo: ensure coverage for these existing tests
 
   //  private void validateEntity(BlueprintEntity entity, boolean containsConfig) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/9bbc0ef7/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintValidatorImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintValidatorImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintValidatorImplTest.java
index a706428..75a9d6b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintValidatorImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintValidatorImplTest.java
@@ -228,6 +228,9 @@ public class BlueprintValidatorImplTest {
 
     services.addAll(Arrays.asList("HIVE"));
 
+    org.apache.ambari.server.configuration.Configuration serverConfig =
+        BlueprintImplTest.setupConfigurationWithGPLLicense(true);
+
     Configuration config = new Configuration(new HashMap<>(), new HashMap<>());
     expect(group1.getConfiguration()).andReturn(config).anyTimes();
 
@@ -237,7 +240,7 @@ public class BlueprintValidatorImplTest {
 
     expect(blueprint.getHostGroupsForComponent("HIVE_METASTORE")).andReturn(Collections.singleton(group1)).anyTimes();
 
-    replay(blueprint, stack, group1, group2, dependency1);
+    replay(blueprint, stack, group1, group2, dependency1, serverConfig);
     BlueprintValidator validator = new BlueprintValidatorImpl(blueprint);
     validator.validateRequiredProperties();
   }
@@ -252,6 +255,9 @@ public class BlueprintValidatorImplTest {
 
     services.addAll(Arrays.asList("OOZIE"));
 
+    org.apache.ambari.server.configuration.Configuration serverConfig =
+        BlueprintImplTest.setupConfigurationWithGPLLicense(true);
+
     Configuration config = new Configuration(new HashMap<>(), new HashMap<>());
     expect(group1.getConfiguration()).andReturn(config).anyTimes();
 
@@ -261,7 +267,7 @@ public class BlueprintValidatorImplTest {
 
     expect(blueprint.getHostGroupsForComponent("OOZIE_SERVER")).andReturn(Collections.singleton(group1)).anyTimes();
 
-    replay(blueprint, stack, group1, group2, dependency1);
+    replay(blueprint, stack, group1, group2, dependency1, serverConfig);
     BlueprintValidator validator = new BlueprintValidatorImpl(blueprint);
     validator.validateRequiredProperties();
   }


[23/50] [abbrv] ambari git commit: AMBARI-22531 Log Search UI: refine search box. (ababiichuk)

Posted by ao...@apache.org.
AMBARI-22531 Log Search UI: refine search box. (ababiichuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2bf3c8ed
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2bf3c8ed
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2bf3c8ed

Branch: refs/heads/branch-3.0-perf
Commit: 2bf3c8edb26a6f0aac43699483e5ebee89dcc533
Parents: 33ee1a7
Author: ababiichuk <ab...@hortonworks.com>
Authored: Tue Nov 28 16:13:51 2017 +0200
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Tue Nov 28 16:49:30 2017 +0200

----------------------------------------------------------------------
 .../src/app/classes/filtering.ts                |  22 +++-
 .../src/app/classes/models/app-state.ts         |   3 +-
 .../classes/queries/audit-logs-query-params.ts  |   3 +-
 .../service-logs-truncated-query-params.ts      |   3 +-
 .../src/app/classes/string.ts                   |  25 ++++
 .../filters-panel/filters-panel.component.html  |   8 +-
 .../filters-panel.component.spec.ts             |   1 +
 .../filters-panel/filters-panel.component.ts    |  99 ++++++++-------
 .../logs-container.component.html               |   2 +-
 .../logs-container/logs-container.component.ts  |   5 +-
 .../src/app/components/mixins.less              |   2 +-
 .../search-box/search-box.component.html        |  24 ++--
 .../search-box/search-box.component.less        |  23 ++--
 .../search-box/search-box.component.ts          | 122 ++++++++++++++-----
 .../src/app/components/variables.less           |   6 +-
 .../services/component-actions.service.spec.ts  |   4 +-
 .../app/services/component-actions.service.ts   |   2 +-
 .../component-generator.service.spec.ts         |   4 +-
 .../app/services/logs-container.service.spec.ts |   4 +-
 .../src/app/services/logs-container.service.ts  |  69 ++++++++---
 .../src/app/services/utils.service.ts           |   4 +
 21 files changed, 303 insertions(+), 132 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/classes/filtering.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/filtering.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/filtering.ts
index 2a7205f..d92dd41 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/filtering.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/filtering.ts
@@ -18,9 +18,10 @@
 
 import {Moment, unitOfTime} from 'moment';
 import {ListItem} from '@app/classes/list-item';
+import {TimeRangeType, SortingType} from '@app/classes/string';
 
 export interface TimeUnit {
-  type: 'CURRENT' | 'LAST' | 'PAST';
+  type: TimeRangeType;
   unit: unitOfTime.DurationConstructor;
   interval?: number;
 }
@@ -33,7 +34,7 @@ export interface CustomTimeRange {
 
 export interface SortingConditions {
   key: string;
-  type: 'asc' | 'desc';
+  type: SortingType;
 }
 
 export interface TimeUnitListItem extends ListItem {
@@ -49,4 +50,21 @@ export interface FilterCondition {
   options?: (ListItem | TimeUnitListItem[])[];
   defaultSelection?: ListItem | ListItem[] | number;
   iconClass?: string;
+  fieldName?: string;
+}
+
+export interface SearchBoxParameter {
+  name: string;
+  value: string;
+  isExclude: boolean;
+}
+
+export interface SearchBoxParameterProcessed extends SearchBoxParameter {
+  id: number;
+  label: string;
+}
+
+export interface SearchBoxParameterTriggered {
+  value: string;
+  isExclude: boolean;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/app-state.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/app-state.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/app-state.ts
index afed497..c3279ce 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/app-state.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/app-state.ts
@@ -17,12 +17,13 @@
  */
 
 import {ActiveServiceLogEntry} from '@app/classes/active-service-log-entry';
+import {LogsType} from '@app/classes/string';
 
 export interface AppState {
   isAuthorized: boolean;
   isInitialLoading: boolean;
   isLoginInProgress: boolean;
-  activeLogsType?: string;
+  activeLogsType?: LogsType;
   isServiceLogsFileView: boolean;
   isServiceLogContextView: boolean;
   activeLog: ActiveServiceLogEntry | null;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-query-params.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-query-params.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-query-params.ts
index 509fa04..3b38a03 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-query-params.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/audit-logs-query-params.ts
@@ -17,6 +17,7 @@
  */
 
 import {QueryParams} from '@app/classes/queries/query-params';
+import {SortingType} from '@app/classes/string';
 
 export const defaultParams = {
   page: '0',
@@ -35,7 +36,7 @@ export class AuditLogsQueryParams extends QueryParams {
   pageSize: string;
   startIndex: string;
   sortBy?: string;
-  sortType?: 'asc' | 'desc';
+  sortType?: SortingType;
   clusters?: string;
   mustBe?: string;
   mustNot?: string;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-truncated-query-params.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-truncated-query-params.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-truncated-query-params.ts
index 6f9de16..3b08e11 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-truncated-query-params.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/queries/service-logs-truncated-query-params.ts
@@ -17,6 +17,7 @@
  */
 
 import {QueryParams} from '@app/classes/queries/query-params';
+import {ScrollType} from '@app/classes/string';
 
 export const defaultParams = {
   numberRows: '10',
@@ -32,5 +33,5 @@ export class ServiceLogsTruncatedQueryParams extends QueryParams {
   host_name: string;
   component_name: string;
   numberRows: string;
-  scrollType: 'before' | 'after' | '';
+  scrollType: ScrollType;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/classes/string.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/string.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/string.ts
new file mode 100644
index 0000000..21ff4ca
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/string.ts
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+export type LogsType = 'auditLogs' | 'serviceLogs';
+
+export type TimeRangeType = 'CURRENT' | 'LAST' | 'PAST';
+
+export type SortingType = 'asc' | 'desc';
+
+export type ScrollType = 'before' | 'after' | '';

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
index 2d327a6..4fe169d 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html
@@ -20,9 +20,9 @@
     <filter-dropdown *ngIf="isFilterConditionDisplayed('clusters')" [label]="filters.clusters.label"
                      formControlName="clusters" [options]="filters.clusters.options" [isMultipleChoice]="true"
                      class="filter-input"></filter-dropdown>
-    <search-box formControlName="query" [items]="searchBoxItemsTranslated" class="filter-input"
-                [parameterNameChangeSubject]="queryParameterNameChange"
-                [parameterAddSubject]="queryParameterAdd"></search-box>
+    <search-box [parameterAddSubject]="queryParameterAdd" [parameterNameChangeSubject]="queryParameterNameChange"
+                formControlName="query" [items]="searchBoxItemsTranslated" [itemsOptions]="options"
+                class="filter-input"></search-box>
     <time-range-picker *ngIf="isFilterConditionDisplayed('timeRange')" formControlName="timeRange"
                        class="filter-input"></time-range-picker>
     <timezone-picker class="filter-input"></timezone-picker>
@@ -31,7 +31,7 @@
     </button-->
   </div>
   <div class="filter-buttons col-md-4">
-    <dropdown-button [options]="searchBoxItems" iconClass="fa fa-search-minus" label="filter.excluded"
+    <dropdown-button [options]="searchBoxItems | async" iconClass="fa fa-search-minus" label="filter.excluded"
                      [hideCaret]="true" [showSelectedValue]="false" action="proceedWithExclude"></dropdown-button>
     <filter-button *ngIf="isFilterConditionDisplayed('hosts')" formControlName="hosts"
                    label="{{filters.hosts.label | translate}}" [iconClass]="filters.hosts.iconClass"

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
index 1f7e8db..c9f9b52 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.spec.ts
@@ -106,6 +106,7 @@ describe('FiltersPanelComponent', () => {
     component.filtersForm = new FormGroup({
       control: new FormControl()
     });
+    component.logsType = 'auditLogs';
     fixture.detectChanges();
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
index b41f7cd..01a8932 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
@@ -16,74 +16,83 @@
  * limitations under the License.
  */
 
-import {Component, Input} from '@angular/core';
+import {Component, OnChanges, SimpleChanges, Input} from '@angular/core';
 import {FormGroup} from '@angular/forms';
+import {Observable} from 'rxjs/Observable';
 import {Subject} from 'rxjs/Subject';
-import {TranslateService} from '@ngx-translate/core';
+import {FilterCondition} from '@app/classes/filtering';
 import {ListItem} from '@app/classes/list-item';
+import {LogsType} from '@app/classes/string';
 import {CommonEntry} from '@app/classes/models/common-entry';
-import {LogField} from '@app/classes/models/log-field';
 import {LogsContainerService} from '@app/services/logs-container.service';
-import {AppStateService} from '@app/services/storage/app-state.service';
 
 @Component({
   selector: 'filters-panel',
   templateUrl: './filters-panel.component.html',
   styleUrls: ['./filters-panel.component.less']
 })
-export class FiltersPanelComponent {
+export class FiltersPanelComponent implements OnChanges {
 
-  constructor(
-    private translate: TranslateService, private logsContainer: LogsContainerService,
-    private appState: AppStateService
-  ) {
-    appState.getParameter('activeLogsType').subscribe(value => {
-      this.logsType = value;
-      logsContainer.logsTypeMap[value].fieldsModel.getAll().subscribe((fields: LogField[]): void => {
-        if (fields.length) {
-          const items = fields.filter((field: LogField): boolean => {
-              return this.excludedParameters.indexOf(field.name) === -1;
-            }).map((field: LogField): CommonEntry => {
-              return {
-                name: field.displayName || field.name,
-                value: field.name
-              };
-            }),
-            labelKeys = items.map((item: CommonEntry): string => item.name);
-          this.searchBoxItems = items.map((item: CommonEntry): ListItem => {
-            return {
-              label: item.name,
-              value: item.value
-            };
-          });
-          translate.get(labelKeys).first().subscribe((translation: {[key: string]: string}): void => {
-            this.searchBoxItemsTranslated = items.map((item: CommonEntry): CommonEntry => {
-              return {
-                name: translation[item.name],
-                value: item.value
-              };
-            })
-          });
-        }
-      })
-    });
+  constructor(private logsContainer: LogsContainerService) {
+  }
+
+  ngOnChanges(changes: SimpleChanges): void {
+    if (changes.hasOwnProperty('logsType')) {
+      let result;
+      switch (changes.logsType.currentValue) {
+        case 'auditLogs':
+          result = this.logsContainer.auditLogsColumns;
+          break;
+        case 'serviceLogs':
+          result = this.logsContainer.serviceLogsColumns;
+          break;
+      }
+      this.searchBoxItems = result;
+    }
   }
 
   @Input()
   filtersForm: FormGroup;
 
-  private readonly excludedParameters = ['cluster', 'host', 'level', 'type', 'logtime'];
-
-  private logsType: string;
+  @Input()
+  logsType: LogsType;
 
-  searchBoxItems: ListItem[] = [];
+  searchBoxItems: Observable<ListItem[]>;
 
-  searchBoxItemsTranslated: CommonEntry[] = [];
+  get searchBoxItemsTranslated(): CommonEntry[] {
+    switch (this.logsType) {
+      case 'auditLogs':
+        return this.logsContainer.auditLogsColumnsTranslated;
+      case 'serviceLogs':
+        return this.logsContainer.serviceLogsColumnsTranslated;
+    }
+  }
 
-  get filters(): any {
+  get filters(): {[key: string]: FilterCondition} {
     return this.logsContainer.filters;
   }
 
+  /**
+   * Object with options for search box parameter values
+   * @returns {[key: string]: CommonEntry[]}
+   */
+  get options(): {[key: string]: CommonEntry[]} {
+    return Object.keys(this.filters).filter((key: string): boolean => {
+      const condition = this.filters[key];
+      return Boolean(condition.fieldName && condition.options);
+    }).reduce((currentValue, currentKey) => {
+      const condition = this.filters[currentKey];
+      return Object.assign(currentValue, {
+        [condition.fieldName]: condition.options.map((option: ListItem): CommonEntry => {
+          return {
+            name: option.value,
+            value: option.value
+          }
+        })
+      });
+    }, {});
+  }
+
   get queryParameterNameChange(): Subject<any> {
     return this.logsContainer.queryParameterNameChange;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
index f34dd15..13911bd 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
@@ -25,7 +25,7 @@
   </div>
 </div>
 <div class="container-fluid">
-  <filters-panel class="row" [filtersForm]="filtersForm"></filters-panel>
+  <filters-panel class="row" [filtersForm]="filtersForm" [logsType]="logsType"></filters-panel>
   <div class="row">
     <div *ngIf="autoRefreshRemainingSeconds" class="col-md-12">
       <div class="auto-refresh-message pull-right">

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
index b06cfa4..86709fb 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
@@ -30,6 +30,7 @@ import {BarGraph} from '@app/classes/models/bar-graph';
 import {ActiveServiceLogEntry} from '@app/classes/active-service-log-entry';
 import {HistogramOptions} from '@app/classes/histogram-options';
 import {ListItem} from '@app/classes/list-item';
+import {LogsType} from '@app/classes/string';
 
 @Component({
   selector: 'logs-container',
@@ -43,7 +44,7 @@ export class LogsContainerComponent {
     private tabsStorage: TabsService, private logsContainer: LogsContainerService
   ) {
     this.logsContainer.loadColumnsNames();
-    appState.getParameter('activeLogsType').subscribe((value: string) => this.logsType = value);
+    appState.getParameter('activeLogsType').subscribe((value: LogsType) => this.logsType = value);
     serviceLogsHistogramStorage.getAll().subscribe((data: BarGraph[]): void => {
       this.histogramData = this.logsContainer.getHistogramData(data);
     });
@@ -56,7 +57,7 @@ export class LogsContainerComponent {
     return this.logsContainer.filtersForm;
   };
 
-  private logsType: string;
+  private logsType: LogsType;
 
   get totalCount(): number {
     return this.logsContainer.totalCount;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
index 5fa265b..4460821 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less
@@ -80,7 +80,7 @@
 
 .dropdown-list-default {
   line-height: 1;
-  border-radius: 2px;
+  border-radius: @dropdown-border-radius;
   font-size: 14px;
   min-width: @dropdown-min-width;
   background: #FFF;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
index 92f9520..5bffdc5 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.html
@@ -16,17 +16,25 @@
 -->
 
 <label class="parameter-label" *ngFor="let parameter of parameters">
-  <span *ngIf="parameter.isExclude" class="fa fa-search-minus exclude-icon"></span>
+  <span *ngIf="parameter.isExclude" class="fa fa-search-minus"></span>
   {{parameter.label | translate}}:
   <span class="parameter-value">{{parameter.value}}</span>
   <span class="fa fa-times remove-parameter" (click)="removeParameter($event, parameter.id)"></span>
 </label>
 <span class="active-parameter-label" *ngIf="isActive && activeItem">{{activeItem.name | translate}}:</span>
 <div [ngClass]="{'search-item-container': true, 'active': isActive, 'value': isValueInput}">
-  <input #parameterInput auto-complete [(ngModel)]="currentValue" [source]="items" [list-formatter]="itemsListFormatter"
-         display-property-name="name" (valueChanged)="changeParameterName({item: $event, isExclude: false})"
-         class="search-item-input parameter-input form-control">
-  <input #valueInput type="text" [(ngModel)]="currentValue" class="search-item-input value-input form-control"
-         (keyup)="onParameterValueChange($event)">
-  <div class="search-item-text" [innerHTML]="currentValue"></div>
-</div>
\ No newline at end of file
+  <span class="parameter-input-wrapper">
+    <input #parameterInput auto-complete class="search-item-input parameter-input form-control"
+           [(ngModel)]="currentValue" [source]="items" display-property-name="name"
+           [list-formatter]="itemsListFormatter" [value-formatter]="itemsValueFormatter" [match-formatted]="true"
+           (valueChanged)="changeParameterName({value: $event.value, isExclude: false})"
+           (keyup)="onParameterKeyUp($event)">
+  </span>
+  <span [ngClass]="{'no-value-options': !activeItemValueOptions.length}">
+    <input #valueInput auto-complete [(ngModel)]="currentValue" [source]="activeItemValueOptions"
+           [list-formatter]="itemsListFormatter" [value-formatter]="itemsValueFormatter" [match-formatted]="true"
+           (valueChanged)="onParameterValueChange($event.value)" (keydown)="onParameterValueKeyDown($event)"
+           (keyup)="onParameterValueKeyUp($event)" class="search-item-input value-input form-control">
+  </span>
+  <div class="search-item-text">{{currentValue}}</div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
index f0a5ce0..eac3bd6 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less
@@ -35,16 +35,13 @@
   cursor: text;
 
   .parameter-label {
-    // TODO implement actual styles
     margin: @label-margin;
-    padding: @label-margin;
-    background-color: @main-background-color;
+    border-radius: @dropdown-border-radius;
+    padding: @search-parameter-padding;
+    background-color: @search-parameter-background-color;
+    color: @base-font-color;
     font-size: 0.8em;
 
-    .exclude-icon {
-      color: @exclude-color;
-    }
-
     .parameter-value {
       font-weight: normal;
     }
@@ -94,8 +91,16 @@
       }
 
       &.value {
-        /deep/ .ng2-auto-complete-wrapper, .parameter-input {
-          display: none;
+        .parameter-input-wrapper {
+          /deep/ .ng2-auto-complete-wrapper {
+            display: none;
+          }
+        }
+
+        .no-value-options {
+          /deep/ .ng2-auto-complete {
+            display: none;
+          }
         }
 
         .value-input {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
index 18ff715..14cc89b 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.ts
@@ -19,6 +19,7 @@
 import {Component, OnInit, OnDestroy, Input, ViewChild, ElementRef, forwardRef} from '@angular/core';
 import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
 import {Subject} from 'rxjs/Subject';
+import {SearchBoxParameter, SearchBoxParameterProcessed, SearchBoxParameterTriggered} from '@app/classes/filtering';
 import {CommonEntry} from '@app/classes/models/common-entry';
 import {UtilsService} from '@app/services/utils.service';
 
@@ -42,7 +43,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.rootElement.addEventListener('keydown', this.onRootKeyDown);
   }
 
-  ngOnInit() {
+  ngOnInit(): void {
     this.parameterInput = this.parameterInputRef.nativeElement;
     this.valueInput = this.valueInputRef.nativeElement;
     this.parameterInput.addEventListener('focus', this.onParameterInputFocus);
@@ -52,7 +53,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.parameterAddSubject.subscribe(this.onParameterAdd);
   }
 
-  ngOnDestroy() {
+  ngOnDestroy(): void {
     this.rootElement.removeEventListener('click', this.onRootClick);
     this.rootElement.removeEventListener('keydown', this.onRootKeyDown);
     this.parameterInput.removeEventListener('focus', this.onParameterInputFocus);
@@ -62,6 +63,8 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.parameterAddSubject.unsubscribe();
   }
 
+  private readonly messageParameterName: string = 'log_message';
+
   private currentId: number = 0;
 
   private isExclude: boolean = false;
@@ -80,10 +83,13 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
   items: CommonEntry[] = [];
 
   @Input()
-  parameterNameChangeSubject: Subject<any> = this.defaultSubject;
+  itemsOptions: {[key: string]: CommonEntry[]};
+
+  @Input()
+  parameterNameChangeSubject: Subject<SearchBoxParameterTriggered> = this.defaultSubject;
 
   @Input()
-  parameterAddSubject: Subject<any> = this.defaultSubject;
+  parameterAddSubject: Subject<SearchBoxParameter> = this.defaultSubject;
 
   @ViewChild('parameterInput')
   parameterInputRef: ElementRef;
@@ -93,13 +99,18 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
 
   private rootElement: HTMLElement;
 
-  private parameterInput: HTMLElement;
+  private parameterInput: HTMLInputElement;
+
+  private valueInput: HTMLInputElement;
 
-  private valueInput: HTMLElement;
+  activeItem: CommonEntry | null = null;
 
-  activeItem?: any;
+  parameters: SearchBoxParameterProcessed[] = [];
 
-  parameters: any[] = [];
+  get activeItemValueOptions(): CommonEntry[] {
+    return this.itemsOptions && this.activeItem && this.itemsOptions[this.activeItem.value] ?
+      this.itemsOptions[this.activeItem.value] : [];
+  }
 
   private onChange: (fn: any) => void;
 
@@ -133,52 +144,80 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     }
   };
 
-  private getItem(name: string): CommonEntry {
-    return this.items.find(field => field.value === name);
+  private switchToParameterInput = (): void => {
+    this.activeItem = null;
+    this.isValueInput = false;
+    setTimeout(() => this.parameterInput.focus());
+  };
+
+  private getItemByValue(name: string): CommonEntry {
+    return this.items.find((field: CommonEntry): boolean => field.value === name);
+  }
+
+  private getItemByName(name: string): CommonEntry {
+    return this.items.find((field: CommonEntry): boolean => field.name === name);
   }
 
   clear(): void {
     this.isActive = false;
     this.activeItem = null;
-    this.currentValue = null;
+    this.currentValue = '';
+    this.parameterInput.value = '';
+    this.valueInput.value = '';
   }
 
   itemsListFormatter(item: CommonEntry): string {
     return item.name;
   }
 
-  changeParameterName(item: any): void {
-    this.parameterNameChangeSubject.next(item);
+  itemsValueFormatter(item: CommonEntry): string {
+    return item.value;
   }
 
-  onParameterNameChange = (options: any): void => {
-    this.activeItem = typeof options.item === 'string' ? this.getItem(options.item) : options.item;
-    this.isExclude = options.isExclude;
-    this.isActive = true;
-    this.isParameterInput = false;
-    this.isValueInput = true;
-    this.currentValue = '';
-    setTimeout(() => this.valueInput.focus(), 0);
+  changeParameterName(options: SearchBoxParameterTriggered): void {
+    this.parameterNameChangeSubject.next(options);
+  }
+
+  onParameterNameChange = (options: SearchBoxParameterTriggered): void => {
+    if (options.value) {
+      this.activeItem = this.getItemByValue(options.value);
+      this.isExclude = options.isExclude;
+      this.isActive = true;
+      this.isParameterInput = false;
+      this.isValueInput = true;
+      this.currentValue = '';
+      setTimeout(() => this.valueInput.focus(), 0);
+    }
   };
 
-  onParameterValueChange(event: KeyboardEvent): void {
+  onParameterValueKeyDown(event: KeyboardEvent): void {
+    if (this.utils.isBackSpacePressed(event) && !this.currentValue) {
+      this.switchToParameterInput();
+    }
+  }
+
+  onParameterValueKeyUp(event: KeyboardEvent): void {
     if (this.utils.isEnterPressed(event) && this.currentValue) {
+      this.onParameterValueChange(this.currentValue);
+    }
+  }
+
+  onParameterValueChange(value: string): void {
+    if (value) {
       this.parameters.push({
         id: this.currentId++,
         name: this.activeItem.value,
         label: this.activeItem.name,
-        value: this.currentValue,
+        value: value,
         isExclude: this.isExclude
       });
-      this.currentValue = '';
-      this.activeItem = null;
-      this.isValueInput = false;
       this.updateValue();
     }
+    this.switchToParameterInput();
   }
 
-  onParameterAdd = (options: any): void => {
-    const item = this.getItem(options.name);
+  onParameterAdd = (options: SearchBoxParameter): void => {
+    const item = this.getItemByValue(options.name);
     this.parameters.push({
       id: this.currentId++,
       name: options.name,
@@ -189,19 +228,38 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.updateValue();
   };
 
+  onParameterKeyUp = (event: KeyboardEvent): void => {
+    if (this.utils.isEnterPressed(event) && this.currentValue) {
+      const existingItem = this.getItemByName(this.currentValue);
+      if (existingItem) {
+        this.changeParameterName({
+          value: this.currentValue,
+          isExclude: false
+        });
+      } else {
+        this.parameterAddSubject.next({
+          name: this.messageParameterName,
+          value: this.currentValue,
+          isExclude: false
+        });
+      }
+    }
+  };
+
   removeParameter(event: MouseEvent, id: number): void {
-    this.parameters = this.parameters.filter(parameter => parameter.id !== id);
+    this.parameters = this.parameters.filter((parameter: SearchBoxParameterProcessed): boolean => parameter.id !== id);
     this.updateValue();
     event.stopPropagation();
   }
 
-  updateValue() {
+  updateValue(): void {
+    this.currentValue = '';
     if (this.onChange) {
       this.onChange(this.parameters);
     }
   }
 
-  writeValue(parameters: any [] = []) {
+  writeValue(parameters: SearchBoxParameterProcessed[] = []): void {
     this.parameters = parameters;
     this.updateValue();
   }
@@ -210,7 +268,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy, ControlValueAccess
     this.onChange = callback;
   }
 
-  registerOnTouched() {
+  registerOnTouched(): void {
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
index 7b7fcae..18268ad 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less
@@ -23,7 +23,6 @@
 @button-border-radius: 4px;
 @input-border-width: 1px;
 @input-border: @input-border-width solid #CFD3D7;
-@button-border-radius: 4px;
 @input-group-addon-padding: 6px 12px 6px 0;
 @block-margin-top: 20px;
 @link-color: #1491C1;
@@ -37,9 +36,11 @@
 @checkbox-top: 4px;
 @dropdown-min-width: 160px;
 @dropdown-max-height: 500px; // TODO get rid of magic number, base on actual design
+@dropdown-border-radius: 2px;
 @input-height: 34px;
 @input-padding: 10px;
 @col-padding: 15px;
+@search-parameter-padding: 5px 2px;
 
 @fatal-color: #830A0A;
 @error-color: #E81D1D;
@@ -51,6 +52,7 @@
 @submit-color: #5CB85C;
 @submit-hover-color: #449D44;
 @exclude-color: #EF6162;
+@search-parameter-background-color: #DDD;
 
 // Panels
 @panel-heading: rgba(255, 255, 255, 1);
@@ -63,4 +65,4 @@
 @icon-padding: 5px;
 
 // Table
-@table-border-color: #EEEEEE;
+@table-border-color: #EEE;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
index 6d43ff1..c2cee8d 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.spec.ts
@@ -17,6 +17,7 @@
  */
 
 import {TestBed, inject} from '@angular/core/testing';
+import {TranslationModules} from '@app/test-config.spec';
 import {StoreModule} from '@ngrx/store';
 import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
 import {AppStateService, appState} from '@app/services/storage/app-state.service';
@@ -62,7 +63,8 @@ describe('ComponentActionsService', () => {
           serviceLogsHistogramData,
           serviceLogsTruncated,
           tabs
-        })
+        }),
+        ...TranslationModules
       ],
       providers: [
         ComponentActionsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.ts
index e796183..0fc9fde 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-actions.service.ts
@@ -132,7 +132,7 @@ export class ComponentActionsService {
   }
 
   proceedWithExclude = (item: string): void => this.logsContainer.queryParameterNameChange.next({
-    item: item,
+    value: item,
     isExclude: true
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
index a161190..3f65cd1 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/component-generator.service.spec.ts
@@ -17,6 +17,7 @@
  */
 
 import {TestBed, inject} from '@angular/core/testing';
+import {TranslationModules} from '@app/test-config.spec';
 import {StoreModule} from '@ngrx/store';
 import {HostsService, hosts} from '@app/services/storage/hosts.service';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
@@ -60,7 +61,8 @@ describe('ComponentGeneratorService', () => {
           components,
           serviceLogsTruncated,
           tabs
-        })
+        }),
+        ...TranslationModules
       ],
       providers: [
         ComponentGeneratorService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
index 47cb25d..870058b 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.spec.ts
@@ -17,6 +17,7 @@
  */
 
 import {TestBed, inject} from '@angular/core/testing';
+import {TranslationModules} from '@app/test-config.spec';
 import {StoreModule} from '@ngrx/store';
 import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
 import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
@@ -61,7 +62,8 @@ describe('LogsContainerService', () => {
           hosts,
           serviceLogsTruncated,
           tabs
-        })
+        }),
+        ...TranslationModules
       ],
       providers: [
         AuditLogsService,

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
index a715adc..64b14b8 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
@@ -27,6 +27,7 @@ import 'rxjs/add/operator/first';
 import 'rxjs/add/operator/map';
 import 'rxjs/add/operator/takeUntil';
 import * as moment from 'moment-timezone';
+import {TranslateService} from '@ngx-translate/core';
 import {HttpClientService} from '@app/services/http-client.service';
 import {AuditLogsService} from '@app/services/storage/audit-logs.service';
 import {AuditLogsFieldsService} from '@app/services/storage/audit-logs-fields.service';
@@ -41,8 +42,11 @@ import {ClustersService} from '@app/services/storage/clusters.service';
 import {ComponentsService} from '@app/services/storage/components.service';
 import {HostsService} from '@app/services/storage/hosts.service';
 import {ActiveServiceLogEntry} from '@app/classes/active-service-log-entry';
-import {FilterCondition, TimeUnitListItem, SortingListItem} from '@app/classes/filtering';
+import {
+  FilterCondition, TimeUnitListItem, SortingListItem, SearchBoxParameter, SearchBoxParameterTriggered
+} from '@app/classes/filtering';
 import {ListItem} from '@app/classes/list-item';
+import {LogsType, ScrollType, SortingType} from '@app/classes/string';
 import {Tab} from '@app/classes/models/tab';
 import {LogField} from '@app/classes/models/log-field';
 import {AuditLog} from '@app/classes/models/audit-log';
@@ -51,14 +55,15 @@ import {ServiceLog} from '@app/classes/models/service-log';
 import {ServiceLogField} from '@app/classes/models/service-log-field';
 import {BarGraph} from '@app/classes/models/bar-graph';
 import {NodeItem} from '@app/classes/models/node-item';
+import {CommonEntry} from '@app/classes/models/common-entry';
 
 @Injectable()
 export class LogsContainerService {
 
   constructor(
-    private httpClient: HttpClientService, private auditLogsStorage: AuditLogsService,
-    private auditLogsFieldsStorage: AuditLogsFieldsService, private serviceLogsStorage: ServiceLogsService,
-    private serviceLogsFieldsStorage: ServiceLogsFieldsService,
+    private translate: TranslateService, private httpClient: HttpClientService,
+    private auditLogsStorage: AuditLogsService, private auditLogsFieldsStorage: AuditLogsFieldsService,
+    private serviceLogsStorage: ServiceLogsService, private serviceLogsFieldsStorage: ServiceLogsFieldsService,
     private serviceLogsHistogramStorage: ServiceLogsHistogramDataService,
     private serviceLogsTruncatedStorage: ServiceLogsTruncatedService, private appState: AppStateService,
     private appSettings: AppSettingsService, private tabsStorage: TabsService, private clustersStorage: ClustersService,
@@ -78,7 +83,7 @@ export class LogsContainerService {
     this.loadHosts();
     appState.getParameter('activeLog').subscribe((value: ActiveServiceLogEntry | null) => this.activeLog = value);
     appState.getParameter('isServiceLogsFileView').subscribe((value: boolean) => this.isServiceLogsFileView = value);
-    appState.getParameter('activeLogsType').subscribe((value: string) => this.activeLogsType = value);
+    appState.getParameter('activeLogsType').subscribe((value: LogsType) => this.activeLogsType = value);
     appSettings.getParameter('timeZone').subscribe((value: string) => this.timeZone = value || this.defaultTimeZone);
     tabsStorage.mapCollection((tab: Tab): Tab => {
       let currentAppState = tab.appState || {};
@@ -111,6 +116,8 @@ export class LogsContainerService {
         this.loadLogs();
       });
     });
+    this.auditLogsColumns.subscribe(this.getTranslationKeysSubscriber('auditLogsColumnsTranslated'));
+    this.serviceLogsColumns.subscribe(this.getTranslationKeysSubscriber('serviceLogsColumnsTranslated'));
   }
 
   private readonly paginationOptions: string[] = ['10', '25', '50', '100'];
@@ -119,7 +126,8 @@ export class LogsContainerService {
     clusters: {
       label: 'filter.clusters',
       options: [],
-      defaultSelection: []
+      defaultSelection: [],
+      fieldName: 'cluster'
     },
     timeRange: {
       options: [
@@ -346,7 +354,8 @@ export class LogsContainerService {
       label: 'filter.components',
       iconClass: 'fa fa-cubes',
       options: [],
-      defaultSelection: []
+      defaultSelection: [],
+      fieldName: 'type'
     },
     levels: {
       label: 'filter.levels',
@@ -381,13 +390,15 @@ export class LogsContainerService {
           value: 'UNKNOWN'
         }
       ],
-      defaultSelection: []
+      defaultSelection: [],
+      fieldName: 'level'
     },
     hosts: {
       label: 'filter.hosts',
       iconClass: 'fa fa-server',
       options: [],
-      defaultSelection: []
+      defaultSelection: [],
+      fieldName: 'host'
     },
     auditLogsSorting: {
       label: 'sorting.title',
@@ -533,7 +544,7 @@ export class LogsContainerService {
 
   activeLog: ActiveServiceLogEntry | null = null;
 
-  activeLogsType: string;
+  activeLogsType: LogsType;
 
   private filtersFormChange: Subject<any> = new Subject();
 
@@ -561,10 +572,30 @@ export class LogsContainerService {
     }
   }
 
+  private getTranslationKeysSubscriber = (propertyName: string): (items: ListItem[]) => void  => {
+    return (items: ListItem[]): void => {
+      const keys = items.map((item: ListItem): string => item.label);
+      if (keys.length) {
+        this.translate.get(keys).first().subscribe((translation: {[key: string]: string}): void => {
+          this[propertyName] = items.map((item: ListItem): CommonEntry => {
+            return {
+              name: translation[item.label],
+              value: item.value
+            };
+          });
+        });
+      }
+    };
+  };
+
   auditLogsColumns: Observable<ListItem[]> = this.auditLogsFieldsStorage.getAll().map(this.columnsMapper);
 
+  auditLogsColumnsTranslated: CommonEntry[] = [];
+
   serviceLogsColumns: Observable<ListItem[]> = this.serviceLogsFieldsStorage.getAll().map(this.columnsMapper);
 
+  serviceLogsColumnsTranslated: CommonEntry[] = [];
+
   serviceLogs: Observable<ServiceLog[]> = Observable.combineLatest(this.serviceLogsStorage.getAll(), this.serviceLogsColumns).map(this.logsMapper);
 
   auditLogs: Observable<AuditLog[]> = Observable.combineLatest(this.auditLogsStorage.getAll(), this.auditLogsColumns).map(this.logsMapper);
@@ -593,9 +624,9 @@ export class LogsContainerService {
     };
   }
 
-  queryParameterNameChange: Subject<any> = new Subject();
+  queryParameterNameChange: Subject<SearchBoxParameterTriggered> = new Subject();
 
-  queryParameterAdd: Subject<any> = new Subject();
+  queryParameterAdd: Subject<SearchBoxParameter> = new Subject();
 
   private stopTimer: Subject<any> = new Subject();
 
@@ -611,7 +642,7 @@ export class LogsContainerService {
 
   private stopCaptureTime: number;
 
-  loadLogs = (logsType: string = this.activeLogsType): void => {
+  loadLogs = (logsType: LogsType = this.activeLogsType): void => {
     this.httpClient.get(logsType, this.getParams('listFilters')).subscribe((response: Response): void => {
       const jsonResponse = response.json(),
         model = this.logsTypeMap[logsType].logsModel;
@@ -640,7 +671,7 @@ export class LogsContainerService {
     }
   };
 
-  loadLogContext(id: string, hostName: string, componentName: string, scrollType: 'before' | 'after' | '' = ''): void {
+  loadLogContext(id: string, hostName: string, componentName: string, scrollType: ScrollType = ''): void {
     const params = {
       id: id,
       host_name: hostName,
@@ -671,7 +702,7 @@ export class LogsContainerService {
     });
   }
 
-  private getParams(filtersMapName: string, logsType: string = this.activeLogsType): {[key: string]: string} {
+  private getParams(filtersMapName: string, logsType: LogsType = this.activeLogsType): {[key: string]: string} {
     let params = {};
     this.logsTypeMap[logsType][filtersMapName].forEach((key: string): void => {
       const inputValue = this.filtersForm.getRawValue()[key],
@@ -787,11 +818,11 @@ export class LogsContainerService {
     return endMoment ? endMoment.toISOString() : '';
   };
 
-  private getQuery(isExclude: boolean): (value: any[]) => string {
-    return (value: any[]): string => {
+  private getQuery(isExclude: boolean): (value: SearchBoxParameter[]) => string {
+    return (value: SearchBoxParameter[]): string => {
       let parameters;
       if (value && value.length) {
-        parameters = value.filter(item => item.isExclude === isExclude).map(parameter => {
+        parameters = value.filter((item: SearchBoxParameter): boolean => item.isExclude === isExclude).map((parameter: SearchBoxParameter): {[key: string]: string} => {
           return {
             [parameter.name]: parameter.value.replace(/\s/g, '+')
           };
@@ -801,7 +832,7 @@ export class LogsContainerService {
     }
   }
 
-  private getSortType(selection: SortingListItem[] = []): 'asc' | 'desc' {
+  private getSortType(selection: SortingListItem[] = []): SortingType {
     return selection[0] && selection[0].value ? selection[0].value.type : 'desc';
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2bf3c8ed/ambari-logsearch/ambari-logsearch-web/src/app/services/utils.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/utils.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/utils.service.ts
index 175b585..dd9075c 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/utils.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/utils.service.ts
@@ -77,6 +77,10 @@ export class UtilsService {
     return event.keyCode === 13;
   }
 
+  isBackSpacePressed(event: KeyboardEvent): boolean {
+    return event.keyCode === 8;
+  }
+
   isDifferentDates(dateA, dateB, timeZone): boolean {
     const momentA = moment(dateA).tz(timeZone),
       momentB = moment(dateB).tz(timeZone);


[10/50] [abbrv] ambari git commit: AMBARI-22510. Handle new error type from Stack Advisor (akovalenko)

Posted by ao...@apache.org.
AMBARI-22510. Handle new error type from Stack Advisor (akovalenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c5fe6cb9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c5fe6cb9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c5fe6cb9

Branch: refs/heads/branch-3.0-perf
Commit: c5fe6cb96a6530d0fc44c4ffced2ec46db97233b
Parents: 0249073
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Fri Nov 24 11:37:07 2017 +0200
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Fri Nov 24 17:59:19 2017 +0200

----------------------------------------------------------------------
 ambari-web/app/messages.js                      |   5 +-
 ambari-web/app/mixins/common/serverValidator.js |  41 +++++---
 ambari-web/app/styles/application.less          |   3 +-
 .../config_recommendation_popup.hbs             | 102 +++++++++++++------
 .../config_validation_popup.js                  |   7 +-
 .../test/mixins/common/serverValidator_test.js  |  15 +--
 6 files changed, 112 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c5fe6cb9/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 390f803..b294877 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -359,6 +359,7 @@ Em.I18n.translations = {
   'common.rolling.downgrade': 'Rolling Downgrade',
   'common.express.downgrade': 'Express Downgrade',
   'common.views': 'Views',
+  'common.critical.error': 'Critical',
 
   'models.alert_instance.tiggered.verbose': "Occurred on {0} <br> Checked on {1}",
   'models.alert_definition.triggered.verbose': "Occurred on {0}",
@@ -951,8 +952,8 @@ Em.I18n.translations = {
   'installer.step7.popup.validation.failed.body': 'Some services are not properly configured. You have to change the highlighted configs according to the recommended values.',
   'installer.step7.popup.validation.request.failed.body': 'The configuration changes could not be validated for consistency due to an unknown error.  Your changes have not been saved yet.  Would you like to proceed and save the changes?',
   'installer.step7.popup.validation.warning.header': 'Configurations',
-  'installer.step7.popup.validation.warning.body': 'Some service configurations are not configured properly. We recommend you review and change the highlighted configuration values. Are you sure you want to proceed without correcting configurations?',
-  'installer.step7.popup.validation.error.body': 'Service configurations resulted in validation errors. Please address them before proceeding.',
+  'installer.step7.popup.validation.issues.body': 'The following configuration changes are highly recommended, but can be skipped.',
+  'installer.step7.popup.validation.criticalIssues.body': 'You must correct the following critical issues before proceeding:',
   'installer.step7.popup.oozie.derby.warning': 'Derby is not recommended for production use. With Derby, Oozie Server HA and concurrent connection support will not be available.',
   'installer.step7.oozie.database.new': 'New Derby Database',
   'installer.step7.hive.database.new.mysql': 'New MySQL Database',

http://git-wip-us.apache.org/repos/asf/ambari/blob/c5fe6cb9/ambari-web/app/mixins/common/serverValidator.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/serverValidator.js b/ambari-web/app/mixins/common/serverValidator.js
index 319c281..65f43b7 100644
--- a/ambari-web/app/mixins/common/serverValidator.js
+++ b/ambari-web/app/mixins/common/serverValidator.js
@@ -57,7 +57,10 @@ App.ServerValidatorMixin = Em.Mixin.create({
    *
    * @type {Object[]}
    */
-  configErrorList: [],
+  configErrorList: Em.Object.create({
+    issues: [],
+    criticalIssues: []
+  }),
 
   /**
    * Map with allowed error types
@@ -65,6 +68,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @type {Object}
    */
   errorTypes: {
+    CRITICAL_ERROR: 'NOT_APPLICABLE',
     ERROR: 'ERROR',
     WARN: 'WARN',
     GENERAL: 'GENERAL'
@@ -113,10 +117,13 @@ App.ServerValidatorMixin = Em.Mixin.create({
       self = this,
       primary = function() { deferred.resolve(); },
       secondary = function() { deferred.reject('invalid_configs'); };
-    this.set('configErrorList', []);
+    this.set('configErrorList', Em.Object.create({
+      issues: [],
+      criticalIssues: []
+    }));
 
     this.runServerSideValidation().done(function() {
-      if (self.get('configErrorList.length')) {
+      if (self.get('configErrorList.issues.length') || self.get('configErrorList.criticalIssues.length')) {
         App.showConfigValidationPopup(self.get('configErrorList'), primary, secondary);
       } else {
         deferred.resolve();
@@ -228,13 +235,14 @@ App.ServerValidatorMixin = Em.Mixin.create({
     var errorTypes = this.get('errorTypes');
     var error = {
       type: type,
+      isCriticalError: type === errorTypes.CRITICAL_ERROR,
       isError: type === errorTypes.ERROR,
       isWarn: type === errorTypes.WARN,
       isGeneral: type === errorTypes.GENERAL,
       messages: Em.makeArray(messages)
     };
 
-    Em.assert('Unknown config error type ' + type, error.isError || error.isWarn || error.isGeneral);
+    Em.assert('Unknown config error type ' + type, error.isError || error.isWarn || error.isGeneral || error.isCriticalError);
     if (property) {
       error.id = Em.get(property, 'id');
       error.serviceName = Em.get(property, 'serviceDisplayName') || App.StackService.find(Em.get(property, 'serviceName')).get('displayName');
@@ -298,29 +306,33 @@ App.ServerValidatorMixin = Em.Mixin.create({
    */
   collectAllIssues: function(configErrorsMap, generalErrors)  {
     var errorTypes = this.get('errorTypes');
-    var configErrorList = [];
+    var configErrorList = {};
+    configErrorList[errorTypes.WARN] = [];
+    configErrorList[errorTypes.ERROR] = [];
+    configErrorList[errorTypes.CRITICAL_ERROR] = [];
+    configErrorList[errorTypes.GENERAL] = [];
 
     this.get('stepConfigs').forEach(function(service) {
       service.get('configs').forEach(function(property) {
         if (property.get('isVisible') && !property.get('hiddenBySection')) {
           var serverIssue = configErrorsMap[property.get('id')];
           if (serverIssue) {
-            configErrorList.push(this.createErrorMessage(serverIssue.type, property, serverIssue.messages));
+            configErrorList[serverIssue.type].push(this.createErrorMessage(serverIssue.type, property, serverIssue.messages));
           } else if (property.get('warnMessage')) {
-            configErrorList.push(this.createErrorMessage(errorTypes.WARN, property, [property.get('warnMessage')]));
+            configErrorList[errorTypes.WARN].push(this.createErrorMessage(errorTypes.WARN, property, [property.get('warnMessage')]));
           }
         }
       }, this);
     }, this);
 
     generalErrors.forEach(function(serverIssue) {
-      configErrorList.push(this.createErrorMessage(errorTypes.GENERAL, null, serverIssue.messages));
+      configErrorList[errorTypes.GENERAL].push(this.createErrorMessage(errorTypes.GENERAL, null, serverIssue.messages));
     }, this);
 
     Em.keys(configErrorsMap).forEach(function (id) {
-      if (!configErrorList.someProperty('id', id)) {
-        var serverIssue = configErrorsMap[id],
-          filename = Em.get(serverIssue, 'filename'),
+      var serverIssue = configErrorsMap[id];
+      if (!configErrorList[serverIssue.type].someProperty('id', id)) {
+        var filename = Em.get(serverIssue, 'filename'),
           service = App.config.get('serviceByConfigTypeMap')[filename],
           property = {
             id: id,
@@ -328,11 +340,14 @@ App.ServerValidatorMixin = Em.Mixin.create({
             filename: App.config.getOriginalFileName(filename),
             serviceDisplayName: service && Em.get(service, 'displayName')
           };
-        configErrorList.push(this.createErrorMessage(serverIssue.type, property, serverIssue.messages));
+        configErrorList[serverIssue.type].push(this.createErrorMessage(serverIssue.type, property, serverIssue.messages));
       }
     }, this);
 
-    return configErrorList;
+    return Em.Object.create({
+      criticalIssues: configErrorList[errorTypes.CRITICAL_ERROR],
+      issues: configErrorList[errorTypes.ERROR].concat(configErrorList[errorTypes.WARN], configErrorList[errorTypes.GENERAL])
+    });
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/c5fe6cb9/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index df86c7f..2a908b3 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -2308,7 +2308,7 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox {
 .table td.error { background-color: @error-background; }
 .table td.warning { background-color: @warning-background; }
 
-#config-validation-warnings {
+.config-validation-warnings {
   table {
     tbody{
       tr {
@@ -2332,7 +2332,6 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox {
   }
 }
 
-
 @config-dependency-t-name-width: 180px;
 @config-dependency-t-service-width: 100px;
 @config-dependency-t-group-width: 140px;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c5fe6cb9/ambari-web/app/templates/common/modal_popups/config_recommendation_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/modal_popups/config_recommendation_popup.hbs b/ambari-web/app/templates/common/modal_popups/config_recommendation_popup.hbs
index 1fe4d39..07125ac 100644
--- a/ambari-web/app/templates/common/modal_popups/config_recommendation_popup.hbs
+++ b/ambari-web/app/templates/common/modal_popups/config_recommendation_popup.hbs
@@ -16,34 +16,25 @@
 * limitations under the License.
 }}
 
-<p>{{view.messageBody}}</p>
-<div id="config-validation-warnings" class="limited-height-2">
-  <table class="table table-hover">
-    <thead>
-    <tr>
-      <th>{{t common.type}}</th>
-      <th>{{t common.service}}</th>
-      <th>{{t common.property}}</th>
-      <th>{{t common.value}}</th>
-      <th>{{t common.description}}</th>
-    </tr>
-    </thead>
-    <tbody>
-    {{#each error in view.configErrors}}
-      <tr {{bindAttr class="error.isError:error:warning"}}>
-        <td>
-          {{#if error.isError}}
-            {{t common.error}}
-          {{else}}
-            {{t common.warning}}
-          {{/if}}
-        </td>
-
-        {{#if error.isGeneral}}
-          {{#each message in error.messages}}
-            <td colspan="4">{{error.message}}</td>
-          {{/each}}
-        {{else}}
+{{#if view.configErrors.criticalIssues.length}}
+  <p>{{t installer.step7.popup.validation.criticalIssues.body}}</p>
+  <div class="limited-height-2 config-validation-warnings">
+    <table class="table table-hover">
+      <thead>
+      <tr>
+        <th>{{t common.type}}</th>
+        <th>{{t common.service}}</th>
+        <th>{{t common.property}}</th>
+        <th>{{t common.value}}</th>
+        <th>{{t common.description}}</th>
+      </tr>
+      </thead>
+      <tbody>
+      {{#each error in view.configErrors.criticalIssues}}
+        <tr class="error">
+          <td>
+            {{t common.critical}}
+          </td>
           <td>{{error.serviceName}}</td>
           <td>{{error.propertyName}}</td>
           <td>{{error.value}}</td>
@@ -53,9 +44,54 @@
             {{/each}}
             <div class="property-description">{{error.description}}</div>
           </td>
-        {{/if}}
+        </tr>
+      {{/each}}
+      </tbody>
+    </table>
+  </div>
+{{/if}}
+{{#if view.configErrors.issues.length}}
+  <p>{{t installer.step7.popup.validation.issues.body}}</p>
+  <div class="limited-height-2 config-validation-warnings">
+    <table class="table table-hover">
+      <thead>
+      <tr>
+        <th>{{t common.type}}</th>
+        <th>{{t common.service}}</th>
+        <th>{{t common.property}}</th>
+        <th>{{t common.value}}</th>
+        <th>{{t common.description}}</th>
       </tr>
-    {{/each}}
-    </tbody>
-  </table>
-</div>
+      </thead>
+      <tbody>
+      {{#each error in view.configErrors.issues}}
+        <tr {{bindAttr class="error.isError:error:warning"}}>
+          <td>
+            {{#if error.isError}}
+              {{t common.error}}
+            {{else}}
+              {{t common.warning}}
+            {{/if}}
+          </td>
+
+          {{#if error.isGeneral}}
+            {{#each message in error.messages}}
+              <td colspan="4">{{error.message}}</td>
+            {{/each}}
+          {{else}}
+            <td>{{error.serviceName}}</td>
+            <td>{{error.propertyName}}</td>
+            <td>{{error.value}}</td>
+            <td>
+              {{#each message in error.messages}}
+                <div class="property-message">{{message}}</div>
+              {{/each}}
+              <div class="property-description">{{error.description}}</div>
+            </td>
+          {{/if}}
+        </tr>
+      {{/each}}
+      </tbody>
+    </table>
+  </div>
+{{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c5fe6cb9/ambari-web/app/views/common/modal_popups/config_validation/config_validation_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/modal_popups/config_validation/config_validation_popup.js b/ambari-web/app/views/common/modal_popups/config_validation/config_validation_popup.js
index 2fe7b62..07c891e 100644
--- a/ambari-web/app/views/common/modal_popups/config_validation/config_validation_popup.js
+++ b/ambari-web/app/views/common/modal_popups/config_validation/config_validation_popup.js
@@ -43,13 +43,10 @@ App.showConfigValidationPopup = function (configErrors, primary, secondary) {
       this._super();
       secondary();
     },
+    disablePrimary: !!configErrors.get('criticalIssues.length'),
     bodyClass: Em.View.extend({
       templateName: require('templates/common/modal_popups/config_recommendation_popup'),
-      configErrors: configErrors,
-      configValidationError: Em.computed.someBy('configErrors', 'isError', true),
-      messageBody: Em.I18n.t(this.get('configValidationError')
-        ? 'installer.step7.popup.validation.error.body'
-        : 'installer.step7.popup.validation.warning.body')
+      configErrors: configErrors
     })
   });
 };

http://git-wip-us.apache.org/repos/asf/ambari/blob/c5fe6cb9/ambari-web/test/mixins/common/serverValidator_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/serverValidator_test.js b/ambari-web/test/mixins/common/serverValidator_test.js
index cdd69fb..4a12a69 100644
--- a/ambari-web/test/mixins/common/serverValidator_test.js
+++ b/ambari-web/test/mixins/common/serverValidator_test.js
@@ -94,35 +94,35 @@ describe('App.ServerValidatorMixin', function () {
     });
 
     it('should add server warnings', function () {
-      var error = result.find(function(r) { return r.propertyName === 'c1' && r.filename === 'f1'; });
+      var error = result.issues.find(function(r) { return r.propertyName === 'c1' && r.filename === 'f1'; });
       expect(error.type).to.equal('WARN');
       expect(error.messages).to.eql(['warn1']);
     });
 
     it('should add server errors', function () {
-      var error = result.find(function(r) { return r.propertyName === 'c2' && r.filename === 'f2'; });
+      var error = result.issues.find(function(r) { return r.propertyName === 'c2' && r.filename === 'f2'; });
       expect(error.type).to.equal('ERROR');
       expect(error.messages).to.eql(['error2']);
     });
 
     it('should add ui warning', function () {
-      var error = result.find(function(r) { return r.propertyName === 'c3' && r.filename === 'f3'; });
+      var error = result.issues.find(function(r) { return r.propertyName === 'c3' && r.filename === 'f3'; });
       expect(error.type).to.equal('WARN');
       expect(error.messages).to.eql(['warn3']);
     });
 
     it('should add general issues', function () {
-      var error = result.findProperty('type', 'GENERAL');
+      var error = result.issues.findProperty('type', 'GENERAL');
       expect(error.messages).to.eql(['general issue']);
     });
 
     it('should ignore issues for hidden configs', function () {
-      var error = result.find(function(r) { return r.propertyName === 'c4' && r.filename === 'f4'; });
+      var error = result.issues.find(function(r) { return r.propertyName === 'c4' && r.filename === 'f4'; });
       expect(error).to.be.undefined;
     });
 
     it('should add issues for deleted properties', function () {
-      var error = result.find(function(r) { return r.id === 'c5_f5'; });
+      var error = result.issues.find(function(r) { return r.id === 'c5_f5'; });
       expect(error.messages).to.eql(['error5']);
     });
   });
@@ -150,6 +150,7 @@ describe('App.ServerValidatorMixin', function () {
     it('creates warn object', function() {
       expect(instanceObject.createErrorMessage('WARN', property, ['msg1'])).to.eql({
         type: 'WARN',
+        isCriticalError: false,
         isError: false,
         isWarn: true,
         isGeneral: false,
@@ -166,6 +167,7 @@ describe('App.ServerValidatorMixin', function () {
     it('creates error object', function() {
       expect(instanceObject.createErrorMessage('ERROR', $.extend({}, property, {serviceDisplayName: 'S Name'}), ['msg2'])).to.eql({
         type: 'ERROR',
+        isCriticalError: false,
         isError: true,
         isWarn: false,
         isGeneral: false,
@@ -182,6 +184,7 @@ describe('App.ServerValidatorMixin', function () {
     it('creates general issue object', function() {
       expect(instanceObject.createErrorMessage('GENERAL', null, ['msg3'])).to.eql({
         type: 'GENERAL',
+        isCriticalError: false,
         isError: false,
         isWarn: false,
         isGeneral: true,


[48/50] [abbrv] ambari git commit: Merge branch 'trunk' into branch-3.0-perf

Posted by ao...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-AzureDB-CREATE.sql
----------------------------------------------------------------------
diff --cc ambari-server/src/main/resources/Ambari-DDL-AzureDB-CREATE.sql
index 7c004b3,0000000..f9574b7
mode 100644,000000..100644
--- a/ambari-server/src/main/resources/Ambari-DDL-AzureDB-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-AzureDB-CREATE.sql
@@@ -1,2149 -1,0 +1,2176 @@@
 +/*
 +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.
 +*/
 +
 +/*
 +Schema population script for $(AMBARIDBNAME)
 +
 +Use this script in sqlcmd mode, setting the environment variables like this:
 +set AMBARIDBNAME=ambari
 +
 +sqlcmd -S localhost\SQLEXPRESS -i C:\app\ambari-server-1.3.0-SNAPSHOT\resources\Ambari-DDL-SQLServer-CREATE.sql
 +*/
 +
 +
 +------create the database------
 +
 +------create tables and grant privileges to db user---------
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('stack') AND type = 'U')
 +BEGIN
 +CREATE TABLE stack(
 +  stack_id BIGINT NOT NULL,
 +  stack_name VARCHAR(255) NOT NULL,
 +  stack_version VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_stack PRIMARY KEY CLUSTERED (stack_id),
 +  CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('extension') AND type = 'U')
 +BEGIN
 +CREATE TABLE extension(
 +  extension_id BIGINT NOT NULL,
 +  extension_name VARCHAR(255) NOT NULL,
 +  extension_version VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_extension PRIMARY KEY CLUSTERED (extension_id),
 +  CONSTRAINT UQ_extension UNIQUE (extension_name, extension_version))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('extensionlink') AND type = 'U')
 +BEGIN
 +CREATE TABLE extensionlink(
 +  link_id BIGINT NOT NULL,
 +  stack_id BIGINT NOT NULL,
 +  extension_id BIGINT NOT NULL,
 +  CONSTRAINT PK_extensionlink PRIMARY KEY CLUSTERED (link_id),
 +  CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
 +  CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id),
 +  CONSTRAINT UQ_extension_link UNIQUE (stack_id, extension_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('adminresourcetype') AND type = 'U')
 +BEGIN
 +CREATE TABLE adminresourcetype (
 +  resource_type_id INTEGER NOT NULL,
 +  resource_type_name VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_adminresourcetype PRIMARY KEY CLUSTERED (resource_type_id)
 +  )
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('adminresource') AND type = 'U')
 +BEGIN
 +CREATE TABLE adminresource (
 +  resource_id BIGINT NOT NULL,
 +  resource_type_id INTEGER NOT NULL,
 +  CONSTRAINT PK_adminresource PRIMARY KEY CLUSTERED (resource_id),
 +  CONSTRAINT FK_resource_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('clusters') AND type = 'U')
 +BEGIN
 +CREATE TABLE clusters (
 +  cluster_id BIGINT NOT NULL,
 +  resource_id BIGINT NOT NULL,
 +  upgrade_id BIGINT,
 +  cluster_info VARCHAR(255) NOT NULL,
 +  cluster_name VARCHAR(100) NOT NULL UNIQUE,
 +  provisioning_state VARCHAR(255) NOT NULL DEFAULT 'INIT',
 +  security_type VARCHAR(32) NOT NULL DEFAULT 'NONE',
 +  desired_cluster_state VARCHAR(255) NOT NULL,
 +  desired_stack_id BIGINT NOT NULL,
 +  CONSTRAINT PK_clusters PRIMARY KEY CLUSTERED (cluster_id),
 +  CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
 +  CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('clusterconfig') AND type = 'U')
 +BEGIN
 +CREATE TABLE clusterconfig (
 +  config_id BIGINT NOT NULL,
 +  version_tag VARCHAR(255) NOT NULL,
 +  version BIGINT NOT NULL,
 +  type_name VARCHAR(255) NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  stack_id BIGINT NOT NULL,
 +  selected SMALLINT NOT NULL DEFAULT 0,
 +  config_data VARCHAR(MAX) NOT NULL,
 +  config_attributes VARCHAR(MAX),
 +  create_timestamp BIGINT NOT NULL,
 +  unmapped SMALLINT NOT NULL DEFAULT 0,
 +  selected_timestamp BIGINT NOT NULL DEFAULT 0,
 +  CONSTRAINT PK_clusterconfig PRIMARY KEY CLUSTERED (config_id),
 +  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
 +  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
 +  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
 +  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version))
 +END
 +
 +
++IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('ambari_configuration') AND type = 'U')
++BEGIN
++CREATE TABLE ambari_configuration (
++  category_name VARCHAR(100) NOT NULL,
++  property_name VARCHAR(100) NOT NULL,
++  property_value VARCHAR(255) NOT NULL,
++  CONSTRAINT PK_ambari_configuration PRIMARY KEY (category_name, property_name)
++)
++END
++
++
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('serviceconfig') AND type = 'U')
 +BEGIN
 +CREATE TABLE serviceconfig (
 +  service_config_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  version BIGINT NOT NULL,
 +  create_timestamp BIGINT NOT NULL,
 +  stack_id BIGINT NOT NULL,
 +  user_name VARCHAR(255) NOT NULL DEFAULT '_db',
 +  group_id BIGINT,
 +  note VARCHAR(MAX),
 +  CONSTRAINT PK_serviceconfig PRIMARY KEY CLUSTERED (service_config_id),
 +  CONSTRAINT FK_serviceconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
 +  CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_name, version))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hosts') AND type = 'U')
 +BEGIN
 +CREATE TABLE hosts (
 +  host_id BIGINT NOT NULL,
 +  host_name VARCHAR(255) NOT NULL,
 +  cpu_count INTEGER NOT NULL,
 +  ph_cpu_count INTEGER,
 +  cpu_info VARCHAR(255) NOT NULL,
 +  discovery_status VARCHAR(2000) NOT NULL,
 +  host_attributes VARCHAR(MAX) NOT NULL,
 +  ipv4 VARCHAR(255),
 +  ipv6 VARCHAR(255),
 +  public_host_name VARCHAR(255),
 +  last_registration_time BIGINT NOT NULL,
 +  os_arch VARCHAR(255) NOT NULL,
 +  os_info VARCHAR(1000) NOT NULL,
 +  os_type VARCHAR(255) NOT NULL,
 +  rack_info VARCHAR(255) NOT NULL,
 +  total_mem BIGINT NOT NULL,
 +  CONSTRAINT PK_hosts PRIMARY KEY CLUSTERED (host_id),
 +  CONSTRAINT UQ_hosts_host_name UNIQUE (host_name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('serviceconfighosts') AND type = 'U')
 +BEGIN
 +CREATE TABLE serviceconfighosts (
 +  service_config_id BIGINT NOT NULL,
 +  host_id BIGINT NOT NULL,
 +  CONSTRAINT PK_serviceconfighosts PRIMARY KEY CLUSTERED (service_config_id, host_id),
 +  CONSTRAINT FK_scvhosts_host_id FOREIGN KEY (host_id) REFERENCES hosts(host_id),
 +  CONSTRAINT FK_scvhosts_scv FOREIGN KEY (service_config_id) REFERENCES serviceconfig(service_config_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('serviceconfigmapping') AND type = 'U')
 +BEGIN
 +CREATE TABLE serviceconfigmapping (
 +  service_config_id BIGINT NOT NULL,
 +  config_id BIGINT NOT NULL,
 +  CONSTRAINT PK_serviceconfigmapping PRIMARY KEY CLUSTERED (service_config_id, config_id),
 +  CONSTRAINT FK_scvm_config FOREIGN KEY (config_id) REFERENCES clusterconfig(config_id),
 +  CONSTRAINT FK_scvm_scv FOREIGN KEY (service_config_id) REFERENCES serviceconfig(service_config_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('clusterservices') AND type = 'U')
 +BEGIN
 +CREATE TABLE clusterservices (
 +  service_name VARCHAR(255) NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  service_enabled INT NOT NULL,
 +  CONSTRAINT PK_clusterservices PRIMARY KEY CLUSTERED (service_name, cluster_id),
 +  CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('clusterstate') AND type = 'U')
 +BEGIN
 +CREATE TABLE clusterstate (
 +  cluster_id BIGINT NOT NULL,
 +  current_cluster_state VARCHAR(255) NOT NULL,
 +  current_stack_id BIGINT NOT NULL,
 +  CONSTRAINT PK_clusterstate PRIMARY KEY CLUSTERED (cluster_id),
 +  CONSTRAINT FK_clusterstate_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
 +  CONSTRAINT FK_cs_current_stack_id FOREIGN KEY (current_stack_id) REFERENCES stack(stack_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('repo_version') AND type = 'U')
 +BEGIN
 +CREATE TABLE repo_version (
 +  repo_version_id BIGINT NOT NULL,
 +  stack_id BIGINT NOT NULL,
 +  version VARCHAR(255) NOT NULL,
 +  display_name VARCHAR(128) NOT NULL,
 +  repositories VARCHAR(MAX) NOT NULL,
 +  repo_type VARCHAR(255) DEFAULT 'STANDARD' NOT NULL,
 +  hidden SMALLINT NOT NULL DEFAULT 0,
 +  resolved BIT NOT NULL DEFAULT 0,
++  legacy BIT NOT NULL DEFAULT 0,
 +  version_url VARCHAR(1024),
 +  version_xml VARCHAR(MAX),
 +  version_xsd VARCHAR(512),
 +  parent_id BIGINT,
 +  CONSTRAINT PK_repo_version PRIMARY KEY CLUSTERED (repo_version_id),
 +  CONSTRAINT FK_repoversion_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
 +  CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name),
 +  CONSTRAINT UQ_repo_version_stack_id UNIQUE (stack_id, version))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('servicecomponentdesiredstate') AND type = 'U')
 +BEGIN
 +CREATE TABLE servicecomponentdesiredstate (
 +  id BIGINT NOT NULL,
 +  component_name VARCHAR(255) NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  desired_repo_version_id BIGINT NOT NULL,
 +  desired_state VARCHAR(255) NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  recovery_enabled SMALLINT NOT NULL DEFAULT 0,
 +  repo_state VARCHAR(255) NOT NULL DEFAULT 'NOT_REQUIRED',
 +  CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
 +  CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
 +  CONSTRAINT FK_scds_desired_repo_id FOREIGN KEY (desired_repo_version_id) REFERENCES repo_version (repo_version_id),
 +  CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hostcomponentdesiredstate') AND type = 'U')
 +BEGIN
 +CREATE TABLE hostcomponentdesiredstate (
 +  id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  component_name VARCHAR(255) NOT NULL,
 +  desired_state VARCHAR(255) NOT NULL,
 +  host_id BIGINT NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  admin_state VARCHAR(32),
 +  maintenance_state VARCHAR(32) NOT NULL,
 +  restart_required BIT NOT NULL DEFAULT 0,
 +  CONSTRAINT PK_hostcomponentdesiredstate PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT UQ_hcdesiredstate_name UNIQUE (component_name, service_name, host_id, cluster_id),
 +  CONSTRAINT FK_hcdesiredstate_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id),
 +  CONSTRAINT hstcmpnntdesiredstatecmpnntnme FOREIGN KEY (component_name, service_name, cluster_id) REFERENCES servicecomponentdesiredstate (component_name, service_name, cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hostcomponentstate') AND type = 'U')
 +BEGIN
 +CREATE TABLE hostcomponentstate (
 +  id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  component_name VARCHAR(255) NOT NULL,
 +  version VARCHAR(32) NOT NULL DEFAULT 'UNKNOWN',
 +  current_state VARCHAR(255) NOT NULL,
 +  last_live_state VARCHAR(255) NOT NULL DEFAULT 'UNKNOWN',
 +  host_id BIGINT NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  upgrade_state VARCHAR(32) NOT NULL DEFAULT 'NONE',
 +  CONSTRAINT PK_hostcomponentstate PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_hostcomponentstate_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id),
 +  CONSTRAINT hstcomponentstatecomponentname FOREIGN KEY (component_name, service_name, cluster_id) REFERENCES servicecomponentdesiredstate (component_name, service_name, cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_host_component_state')
 +BEGIN
 +CREATE NONCLUSTERED INDEX idx_host_component_state on hostcomponentstate(host_id, component_name, service_name, cluster_id)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hoststate') AND type = 'U')
 +BEGIN
 +CREATE TABLE hoststate (
 +  agent_version VARCHAR(255) NOT NULL,
 +  available_mem BIGINT NOT NULL,
 +  current_state VARCHAR(255) NOT NULL,
 +  health_status VARCHAR(255),
 +  host_id BIGINT NOT NULL,
 +  time_in_state BIGINT NOT NULL,
 +  maintenance_state VARCHAR(512),
 +  CONSTRAINT PK_hoststate PRIMARY KEY CLUSTERED (host_id),
 +  CONSTRAINT FK_hoststate_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('servicedesiredstate') AND type = 'U')
 +BEGIN
 +CREATE TABLE servicedesiredstate (
 +  cluster_id BIGINT NOT NULL,
 +  desired_host_role_mapping INTEGER NOT NULL,
 +  desired_repo_version_id BIGINT NOT NULL,
 +  desired_state VARCHAR(255) NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  maintenance_state VARCHAR(32) NOT NULL,
 +  credential_store_enabled SMALLINT NOT NULL DEFAULT 0,
 +  CONSTRAINT PK_servicedesiredstate PRIMARY KEY CLUSTERED (cluster_id,service_name),
 +  CONSTRAINT FK_repo_version_id FOREIGN KEY (desired_repo_version_id) REFERENCES repo_version (repo_version_id),
 +  CONSTRAINT servicedesiredstateservicename FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('adminprincipaltype') AND type = 'U')
 +BEGIN
 +CREATE TABLE adminprincipaltype (
 +  principal_type_id INTEGER NOT NULL,
 +  principal_type_name VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_adminprincipaltype PRIMARY KEY CLUSTERED (principal_type_id)
 +  )
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('adminprincipal') AND type = 'U')
 +BEGIN
 +CREATE TABLE adminprincipal (
 +  principal_id BIGINT NOT NULL,
 +  principal_type_id INTEGER NOT NULL,
 +  CONSTRAINT PK_adminprincipal PRIMARY KEY CLUSTERED (principal_id),
 +  CONSTRAINT FK_principal_principal_type_id FOREIGN KEY (principal_type_id) REFERENCES adminprincipaltype(principal_type_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('users') AND type = 'U')
 +BEGIN
 +CREATE TABLE users (
 +  user_id INTEGER,
 +  principal_id BIGINT NOT NULL,
 +  ldap_user INTEGER NOT NULL DEFAULT 0,
 +  user_name VARCHAR(255) NOT NULL,
 +  user_type VARCHAR(255) NOT NULL DEFAULT 'LOCAL',
 +  create_time DATETIME DEFAULT GETDATE(),
 +  user_password VARCHAR(255),
 +  active INTEGER NOT NULL DEFAULT 1,
 +  active_widget_layouts VARCHAR(1024) DEFAULT NULL,
 +  CONSTRAINT PK_users PRIMARY KEY CLUSTERED (user_id),
 +  CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
 +  CONSTRAINT UNQ_users_0 UNIQUE (user_name, user_type))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('groups') AND type = 'U')
 +BEGIN
 +CREATE TABLE groups (
 +  group_id INTEGER,
 +  principal_id BIGINT NOT NULL,
 +  group_name VARCHAR(255) NOT NULL,
 +  ldap_group INTEGER NOT NULL DEFAULT 0,
 +  group_type VARCHAR(255) NOT NULL DEFAULT 'LOCAL',
 +  CONSTRAINT PK_groups PRIMARY KEY CLUSTERED (group_id),
 +  CONSTRAINT FK_groups_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
 +  CONSTRAINT UNQ_groups_0 UNIQUE (group_name, ldap_group))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('members') AND type = 'U')
 +BEGIN
 +CREATE TABLE members (
 +  member_id INTEGER,
 +  group_id INTEGER NOT NULL,
 +  user_id INTEGER NOT NULL,
 +  CONSTRAINT PK_members PRIMARY KEY CLUSTERED (member_id),
 +  CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id),
 +  CONSTRAINT FK_members_user_id FOREIGN KEY (user_id) REFERENCES users (user_id),
 +  CONSTRAINT UNQ_members_0 UNIQUE (group_id, user_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('requestschedule') AND type = 'U')
 +BEGIN
 +CREATE TABLE requestschedule (
 +  schedule_id BIGINT,
 +  cluster_id BIGINT NOT NULL,
 +  description VARCHAR(255),
 +  STATUS VARCHAR(255),
 +  batch_separation_seconds SMALLINT,
 +  batch_toleration_limit SMALLINT,
 +  authenticated_user_id INTEGER,
 +  create_user VARCHAR(255),
 +  create_timestamp BIGINT,
 +  update_user VARCHAR(255),
 +  update_timestamp BIGINT,
 +  minutes VARCHAR(10),
 +  hours VARCHAR(10),
 +  days_of_month VARCHAR(10),
 +  month VARCHAR(10),
 +  day_of_week VARCHAR(10),
 +  yearToSchedule VARCHAR(10),
 +  startTime VARCHAR(50),
 +  endTime VARCHAR(50),
 +  last_execution_status VARCHAR(255),
 +  CONSTRAINT PK_requestschedule PRIMARY KEY CLUSTERED (schedule_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('request') AND type = 'U')
 +BEGIN
 +CREATE TABLE request (
 +  request_id BIGINT NOT NULL,
 +  cluster_id BIGINT,
 +  command_name VARCHAR(255),
 +  create_time BIGINT NOT NULL,
 +  end_time BIGINT NOT NULL,
 +  exclusive_execution BIT NOT NULL DEFAULT 0,
 +  inputs VARBINARY(MAX),
 +  request_context VARCHAR(255),
 +  request_type VARCHAR(255),
 +  request_schedule_id BIGINT,
 +  start_time BIGINT NOT NULL,
 +  status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
 +  display_status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
 +  cluster_host_info VARBINARY(MAX) NOT NULL,
 +  CONSTRAINT PK_request PRIMARY KEY CLUSTERED (request_id),
 +  CONSTRAINT FK_request_schedule_id FOREIGN KEY (request_schedule_id) REFERENCES requestschedule (schedule_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('stage') AND type = 'U')
 +BEGIN
 +CREATE TABLE stage (
 +  stage_id BIGINT NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  skippable SMALLINT DEFAULT 0 NOT NULL,
 +  supports_auto_skip_failure SMALLINT DEFAULT 0 NOT NULL,
 +  log_info VARCHAR(255) NOT NULL,
 +  request_context VARCHAR(255),
 +  command_params VARBINARY(MAX),
 +  host_params VARBINARY(MAX),
 +  command_execution_type VARCHAR(32) NOT NULL DEFAULT 'STAGE',
 +  status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
 +  display_status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
 +  CONSTRAINT PK_stage PRIMARY KEY CLUSTERED (stage_id, request_id),
 +  CONSTRAINT FK_stage_request_id FOREIGN KEY (request_id) REFERENCES request (request_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('host_role_command') AND type = 'U')
 +BEGIN
 +CREATE TABLE host_role_command (
 +  task_id BIGINT NOT NULL,
 +  attempt_count SMALLINT NOT NULL,
 +  retry_allowed SMALLINT DEFAULT 0 NOT NULL,
 +  event VARCHAR(MAX) NOT NULL,
 +  exitcode INTEGER NOT NULL,
 +  host_id BIGINT,
 +  last_attempt_time BIGINT NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  role VARCHAR(255),
 +  stage_id BIGINT NOT NULL,
 +  start_time BIGINT NOT NULL,
 +  original_start_time BIGINT NOT NULL,
 +  end_time BIGINT,
 +  status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
 +  auto_skip_on_failure SMALLINT DEFAULT 0 NOT NULL,
 +  std_error VARBINARY(max),
 +  std_out VARBINARY(max),
 +  output_log VARCHAR(255) NULL,
 +  error_log VARCHAR(255) NULL,
 +  structured_out VARBINARY(max),
 +  role_command VARCHAR(255),
 +  command_detail VARCHAR(255),
 +  custom_command_name VARCHAR(255),
 +  is_background SMALLINT DEFAULT 0 NOT NULL,
 +  ops_display_name VARCHAR(255),
 +  CONSTRAINT PK_host_role_command PRIMARY KEY CLUSTERED (task_id),
 +  CONSTRAINT FK_host_role_command_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id),
 +  CONSTRAINT FK_host_role_command_stage_id FOREIGN KEY (stage_id, request_id) REFERENCES stage (stage_id, request_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('execution_command') AND type = 'U')
 +BEGIN
 +CREATE TABLE execution_command (
 +  command VARBINARY(MAX),
 +  task_id BIGINT NOT NULL,
 +  CONSTRAINT PK_execution_command PRIMARY KEY CLUSTERED (task_id),
 +  CONSTRAINT FK_execution_command_task_id FOREIGN KEY (task_id) REFERENCES host_role_command (task_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('role_success_criteria') AND type = 'U')
 +BEGIN
 +CREATE TABLE role_success_criteria (
 +  ROLE VARCHAR(255) NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  stage_id BIGINT NOT NULL,
 +  success_factor FLOAT NOT NULL,
 +  CONSTRAINT PK_role_success_criteria PRIMARY KEY CLUSTERED (ROLE, request_id, stage_id),
 +  CONSTRAINT role_success_criteria_stage_id FOREIGN KEY (stage_id, request_id) REFERENCES stage (stage_id, request_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('requestresourcefilter') AND type = 'U')
 +BEGIN
 +CREATE TABLE requestresourcefilter (
 +  filter_id BIGINT NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  service_name VARCHAR(255),
 +  component_name VARCHAR(255),
 +  hosts VARBINARY(MAX),
 +  CONSTRAINT PK_requestresourcefilter PRIMARY KEY CLUSTERED (filter_id),
 +  CONSTRAINT FK_reqresfilter_req_id FOREIGN KEY (request_id) REFERENCES request (request_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('requestoperationlevel') AND type = 'U')
 +BEGIN
 +CREATE TABLE requestoperationlevel (
 +  operation_level_id BIGINT NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  level_name VARCHAR(255),
 +  cluster_name VARCHAR(255),
 +  service_name VARCHAR(255),
 +  host_component_name VARCHAR(255),
 +  host_id BIGINT NULL,      -- unlike most host_id columns, this one allows NULLs because the request can be at the service level
 +  CONSTRAINT PK_requestoperationlevel PRIMARY KEY CLUSTERED (operation_level_id),
 +  CONSTRAINT FK_req_op_level_req_id FOREIGN KEY (request_id) REFERENCES request (request_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('ClusterHostMapping') AND type = 'U')
 +BEGIN
 +CREATE TABLE ClusterHostMapping (
 +  cluster_id BIGINT NOT NULL,
 +  host_id BIGINT NOT NULL,
 +  CONSTRAINT PK_ClusterHostMapping PRIMARY KEY CLUSTERED (cluster_id, host_id),
 +  CONSTRAINT FK_clhostmapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
 +  CONSTRAINT FK_clusterhostmapping_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('key_value_store') AND type = 'U')
 +BEGIN
 +CREATE TABLE key_value_store (
 +  [key] VARCHAR(255),
 +  [value] VARCHAR(MAX),
 +  CONSTRAINT PK_key_value_store PRIMARY KEY CLUSTERED ([key])
 +  )
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hostconfigmapping') AND type = 'U')
 +BEGIN
 +CREATE TABLE hostconfigmapping (
 +  cluster_id BIGINT NOT NULL,
 +  host_id BIGINT NOT NULL,
 +  type_name VARCHAR(255) NOT NULL,
 +  version_tag VARCHAR(255) NOT NULL,
 +  service_name VARCHAR(255),
 +  create_timestamp BIGINT NOT NULL,
 +  selected INTEGER NOT NULL DEFAULT 0,
 +  user_name VARCHAR(255) NOT NULL DEFAULT '_db',
 +  CONSTRAINT PK_hostconfigmapping PRIMARY KEY CLUSTERED (cluster_id, host_id, type_name, create_timestamp),
 +  CONSTRAINT FK_hostconfmapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
 +  CONSTRAINT FK_hostconfmapping_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('metainfo') AND type = 'U')
 +BEGIN
 +CREATE TABLE metainfo (
 +  [metainfo_key] VARCHAR(255),
 +  [metainfo_value] VARCHAR(255),
 +  CONSTRAINT PK_metainfo PRIMARY KEY CLUSTERED ([metainfo_key])
 +  )
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('ambari_sequences') AND type = 'U')
 +BEGIN
 +CREATE TABLE ambari_sequences (
 +  sequence_name VARCHAR(255),
 +  [sequence_value] BIGINT NOT NULL,
 +  CONSTRAINT PK_ambari_sequences PRIMARY KEY (sequence_name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('configgroup') AND type = 'U')
 +BEGIN
 +CREATE TABLE configgroup (
 +  group_id BIGINT,
 +  cluster_id BIGINT NOT NULL,
 +  group_name VARCHAR(255) NOT NULL,
 +  tag VARCHAR(1024) NOT NULL,
 +  description VARCHAR(1024),
 +  create_timestamp BIGINT NOT NULL,
 +  service_name VARCHAR(255),
 +  CONSTRAINT PK_configgroup PRIMARY KEY CLUSTERED (group_id),
 +  CONSTRAINT FK_configgroup_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('confgroupclusterconfigmapping') AND type = 'U')
 +BEGIN
 +CREATE TABLE confgroupclusterconfigmapping (
 +  config_group_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  config_type VARCHAR(255) NOT NULL,
 +  version_tag VARCHAR(255) NOT NULL,
 +  user_name VARCHAR(255) DEFAULT '_db',
 +  create_timestamp BIGINT NOT NULL,
 +  CONSTRAINT PK_confgroupclustercfgmapping PRIMARY KEY CLUSTERED (config_group_id, cluster_id, config_type),
 +  CONSTRAINT FK_cgccm_gid FOREIGN KEY (config_group_id) REFERENCES configgroup (group_id),
 +  CONSTRAINT FK_confg FOREIGN KEY (cluster_id, config_type, version_tag) REFERENCES clusterconfig (cluster_id, type_name, version_tag))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('configgrouphostmapping') AND type = 'U')
 +BEGIN
 +CREATE TABLE configgrouphostmapping (
 +  config_group_id BIGINT NOT NULL,
 +  host_id BIGINT NOT NULL,
 +  CONSTRAINT PK_configgrouphostmapping PRIMARY KEY CLUSTERED (config_group_id, host_id),
 +  CONSTRAINT FK_cghm_cgid FOREIGN KEY (config_group_id) REFERENCES configgroup (group_id),
 +  CONSTRAINT FK_cghm_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('requestschedulebatchrequest') AND type = 'U')
 +BEGIN
 +CREATE TABLE requestschedulebatchrequest (
 +  schedule_id BIGINT,
 +  batch_id BIGINT,
 +  request_id BIGINT,
 +  request_type VARCHAR(255),
 +  request_uri VARCHAR(1024),
 +  request_body VARBINARY(MAX),
 +  request_status VARCHAR(255),
 +  return_code SMALLINT,
 +  return_message TEXT,
 +  CONSTRAINT PK_requestschedulebatchrequest PRIMARY KEY CLUSTERED (schedule_id, batch_id),
 +  CONSTRAINT FK_rsbatchrequest_schedule_id FOREIGN KEY (schedule_id) REFERENCES requestschedule (schedule_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('blueprint') AND type = 'U')
 +BEGIN
 +CREATE TABLE blueprint (
 +  blueprint_name VARCHAR(255) NOT NULL,
 +  stack_id BIGINT NOT NULL,
 +  security_type VARCHAR(32) NOT NULL DEFAULT 'NONE',
 +  security_descriptor_reference VARCHAR(255),
 +  CONSTRAINT PK_blueprint PRIMARY KEY CLUSTERED (blueprint_name),
 +  CONSTRAINT FK_blueprint_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hostgroup') AND type = 'U')
 +BEGIN
 +CREATE TABLE hostgroup (
 +  blueprint_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  cardinality VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_hostgroup PRIMARY KEY CLUSTERED (blueprint_name, NAME),
 +  CONSTRAINT FK_hg_blueprint_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hostgroup_component') AND type = 'U')
 +BEGIN
 +CREATE TABLE hostgroup_component (
 +  blueprint_name VARCHAR(255) NOT NULL,
 +  hostgroup_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  provision_action VARCHAR(255),
 +  CONSTRAINT PK_hostgroup_component PRIMARY KEY CLUSTERED (blueprint_name, hostgroup_name, NAME),
 +  CONSTRAINT FK_hgc_blueprint_name FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES hostgroup (blueprint_name, name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('blueprint_configuration') AND type = 'U')
 +BEGIN
 +CREATE TABLE blueprint_configuration (
 +  blueprint_name VARCHAR(255) NOT NULL,
 +  type_name VARCHAR(255) NOT NULL,
 +  config_data VARCHAR(MAX) NOT NULL,
 +  config_attributes VARCHAR(MAX),
 +  CONSTRAINT PK_blueprint_configuration PRIMARY KEY CLUSTERED (blueprint_name, type_name),
 +  CONSTRAINT FK_cfg_blueprint_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('blueprint_setting') AND type = 'U')
 +BEGIN
 +CREATE TABLE blueprint_setting (
 +  id BIGINT NOT NULL,
 +  blueprint_name VARCHAR(255) NOT NULL,
 +  setting_name VARCHAR(255) NOT NULL,
 +  setting_data TEXT NOT NULL,
 +  CONSTRAINT PK_blueprint_setting PRIMARY KEY (id),
 +  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
 +  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name)
 +  )
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('hostgroup_configuration') AND type = 'U')
 +BEGIN
 +CREATE TABLE hostgroup_configuration (
 +  blueprint_name VARCHAR(255) NOT NULL,
 +  hostgroup_name VARCHAR(255) NOT NULL,
 +  type_name VARCHAR(255) NOT NULL,
 +  config_data VARCHAR(MAX) NOT NULL,
 +  config_attributes VARCHAR(MAX),
 +  CONSTRAINT PK_hostgroup_configuration PRIMARY KEY CLUSTERED (blueprint_name, hostgroup_name, type_name),
 +  CONSTRAINT FK_hg_cfg_bp_hg_name FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES hostgroup (blueprint_name, name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewmain') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewmain (
 +  view_name VARCHAR(255) NOT NULL,
 +  label VARCHAR(255),
 +  description VARCHAR(2048),
 +  version VARCHAR(255),
 +  build VARCHAR(128),
 +  resource_type_id INTEGER NOT NULL,
 +  icon VARCHAR(255),
 +  icon64 VARCHAR(255),
 +  archive VARCHAR(255),
 +  mask VARCHAR(255),
 +  system_view BIT NOT NULL DEFAULT 0,
 +  CONSTRAINT PK_viewmain PRIMARY KEY CLUSTERED (view_name),
 +  CONSTRAINT FK_view_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id))
 +END
 +
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewurl') AND type = 'U')
 +BEGIN
 +CREATE table viewurl(
 +  url_id BIGINT ,
 +  url_name VARCHAR(255) NOT NULL ,
 +  url_suffix VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_viewurl PRIMARY KEY CLUSTERED (url_id)
 +)
 +END
 +
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewinstance') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewinstance (
 +  view_instance_id BIGINT,
 +  resource_id BIGINT NOT NULL,
 +  view_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  label VARCHAR(255),
 +  description VARCHAR(2048),
 +  visible CHAR(1),
 +  icon VARCHAR(255),
 +  icon64 VARCHAR(255),
 +  xml_driven CHAR(1),
 +  alter_names BIT NOT NULL DEFAULT 1,
 +  cluster_handle BIGINT,
 +  cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI',
 +  short_url BIGINT,
 +  CONSTRAINT PK_viewinstance PRIMARY KEY CLUSTERED (view_instance_id),
 +  CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id),
 +  CONSTRAINT FK_viewinst_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name),
 +  CONSTRAINT FK_viewinstance_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id),
 +  CONSTRAINT UQ_viewinstance_name UNIQUE (view_name, name),
 +  CONSTRAINT UQ_viewinstance_name_id UNIQUE (view_instance_id, view_name, name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewinstancedata') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewinstancedata (
 +  view_instance_id BIGINT,
 +  view_name VARCHAR(255) NOT NULL,
 +  view_instance_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  user_name VARCHAR(255) NOT NULL,
 +  value VARCHAR(2000) NOT NULL,
 +  CONSTRAINT PK_viewinstancedata PRIMARY KEY CLUSTERED (view_instance_id, NAME, user_name),
 +  CONSTRAINT FK_viewinstdata_view_name FOREIGN KEY (view_instance_id, view_name, view_instance_name) REFERENCES viewinstance(view_instance_id, view_name, name))
 +END
 +
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewinstanceproperty') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewinstanceproperty (
 +  view_name VARCHAR(255) NOT NULL,
 +  view_instance_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  value VARCHAR(2000),
 +  CONSTRAINT PK_viewinstanceproperty PRIMARY KEY CLUSTERED (view_name, view_instance_name, NAME),
 +  CONSTRAINT FK_viewinstprop_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewparameter') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewparameter (
 +  view_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  description VARCHAR(2048),
 +  label VARCHAR(255),
 +  placeholder VARCHAR(255),
 +  default_value VARCHAR(2000),
 +  cluster_config VARCHAR(255),
 +  required CHAR(1),
 +  masked CHAR(1),
 +  CONSTRAINT PK_viewparameter PRIMARY KEY CLUSTERED (view_name, NAME),
 +  CONSTRAINT FK_viewparam_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewresource') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewresource (
 +  view_name VARCHAR(255) NOT NULL,
 +  NAME VARCHAR(255) NOT NULL,
 +  plural_name VARCHAR(255),
 +  id_property VARCHAR(255),
 +  subResource_names VARCHAR(255),
 +  provider VARCHAR(255),
 +  service VARCHAR(255),
 +  resource VARCHAR(255),
 +  CONSTRAINT PK_viewresource PRIMARY KEY CLUSTERED (view_name, NAME),
 +  CONSTRAINT FK_viewres_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('viewentity') AND type = 'U')
 +BEGIN
 +CREATE TABLE viewentity (
 +  id BIGINT NOT NULL,
 +  view_name VARCHAR(255) NOT NULL,
 +  view_instance_name VARCHAR(255) NOT NULL,
 +  class_name VARCHAR(255) NOT NULL,
 +  id_property VARCHAR(255),
 +  CONSTRAINT PK_viewentity PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('adminpermission') AND type = 'U')
 +BEGIN
 +CREATE TABLE adminpermission (
 +  permission_id BIGINT NOT NULL,
 +  permission_name VARCHAR(255) NOT NULL,
 +  resource_type_id INTEGER NOT NULL,
 +  permission_label VARCHAR(255),
 +  principal_id BIGINT NOT NULL,
 +  sort_order SMALLINT NOT NULL DEFAULT 1,
 +  CONSTRAINT PK_adminpermission PRIMARY KEY CLUSTERED (permission_id),
 +  CONSTRAINT FK_permission_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id),
 +  CONSTRAINT FK_permission_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
 +  CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('roleauthorization') AND type = 'U')
 +BEGIN
 +CREATE TABLE roleauthorization (
 +  authorization_id VARCHAR(100) NOT NULL,
 +  authorization_name VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_roleauthorization PRIMARY KEY (authorization_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('permission_roleauthorization') AND type = 'U')
 +BEGIN
 +CREATE TABLE permission_roleauthorization (
 +  permission_id BIGINT NOT NULL,
 +  authorization_id VARCHAR(100) NOT NULL,
 +  CONSTRAINT PK_permsn_roleauthorization PRIMARY KEY (permission_id, authorization_id),
 +  CONSTRAINT FK_permission_roleauth_aid FOREIGN KEY (authorization_id) REFERENCES roleauthorization(authorization_id),
 +  CONSTRAINT FK_permission_roleauth_pid FOREIGN KEY (permission_id) REFERENCES adminpermission(permission_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('adminprivilege') AND type = 'U')
 +BEGIN
 +CREATE TABLE adminprivilege (
 +  privilege_id BIGINT,
 +  permission_id BIGINT NOT NULL,
 +  resource_id BIGINT NOT NULL,
 +  principal_id BIGINT NOT NULL,
 +  CONSTRAINT PK_adminprivilege PRIMARY KEY CLUSTERED (privilege_id),
 +  CONSTRAINT FK_privilege_permission_id FOREIGN KEY (permission_id) REFERENCES adminpermission(permission_id),
 +  CONSTRAINT FK_privilege_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id),
 +  CONSTRAINT FK_privilege_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('host_version') AND type = 'U')
 +BEGIN
 +CREATE TABLE host_version (
 +  id BIGINT NOT NULL,
 +  repo_version_id BIGINT NOT NULL,
 +  host_id BIGINT NOT NULL,
 +  STATE VARCHAR(32) NOT NULL,
 +  CONSTRAINT PK_host_version PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_host_version_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id),
 +  CONSTRAINT FK_host_version_repovers_id FOREIGN KEY (repo_version_id) REFERENCES repo_version (repo_version_id),
 +  CONSTRAINT UQ_host_repo UNIQUE(host_id, repo_version_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('artifact') AND type = 'U')
 +BEGIN
 +CREATE TABLE artifact (
 +  artifact_name VARCHAR(255) NOT NULL,
 +  artifact_data TEXT NOT NULL,
 +  foreign_keys VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_artifact PRIMARY KEY CLUSTERED (artifact_name, foreign_keys)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('widget') AND type = 'U')
 +BEGIN
 +CREATE TABLE widget (
 +  id BIGINT NOT NULL,
 +  widget_name VARCHAR(255) NOT NULL,
 +  widget_type VARCHAR(255) NOT NULL,
 +  metrics TEXT,
 +  time_created BIGINT NOT NULL,
 +  author VARCHAR(255),
 +  description VARCHAR(2048),
 +  default_section_name VARCHAR(255),
 +  scope VARCHAR(255),
 +  widget_values VARCHAR(4000),
 +  properties VARCHAR(4000),
 +  cluster_id BIGINT NOT NULL,
 +  CONSTRAINT PK_widget PRIMARY KEY CLUSTERED (id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('widget_layout') AND type = 'U')
 +BEGIN
 +CREATE TABLE widget_layout (
 +  id BIGINT NOT NULL,
 +  layout_name VARCHAR(255) NOT NULL,
 +  section_name VARCHAR(255) NOT NULL,
 +  scope VARCHAR(255) NOT NULL,
 +  user_name VARCHAR(255) NOT NULL,
 +  display_name VARCHAR(255),
 +  cluster_id BIGINT NOT NULL,
 +  CONSTRAINT PK_widget_layout PRIMARY KEY CLUSTERED (id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('widget_layout_user_widget') AND type = 'U')
 +BEGIN
 +CREATE TABLE widget_layout_user_widget (
 +  widget_layout_id BIGINT NOT NULL,
 +  widget_id BIGINT NOT NULL,
 +  widget_order smallint,
 +  CONSTRAINT PK_widget_layout_user_widget PRIMARY KEY CLUSTERED (widget_layout_id, widget_id),
 +  CONSTRAINT FK_widget_id FOREIGN KEY (widget_id) REFERENCES widget(id),
 +  CONSTRAINT FK_widget_layout_id FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_request') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_request (
 +  id BIGINT NOT NULL,
 +  action VARCHAR(255) NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  bp_name VARCHAR(100) NOT NULL,
 +  cluster_properties TEXT,
 +  cluster_attributes TEXT,
 +  description VARCHAR(1024),
 +  provision_action VARCHAR(255),
 +  CONSTRAINT PK_topology_request PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_topology_request_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_hostgroup') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_hostgroup (
 +  id BIGINT NOT NULL,
 +  name VARCHAR(255) NOT NULL,
 +  group_properties TEXT,
 +  group_attributes TEXT,
 +  request_id BIGINT NOT NULL,
 +  CONSTRAINT PK_topology_hostgroup PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_hostgroup_req_id FOREIGN KEY (request_id) REFERENCES topology_request(id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_host_info') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_host_info (
 +  id BIGINT NOT NULL,
 +  group_id BIGINT NOT NULL,
 +  fqdn VARCHAR(255),
 +  host_id BIGINT,
 +  host_count INTEGER,
 +  predicate VARCHAR(2048),
 +  rack_info VARCHAR(255),
 +  CONSTRAINT PK_topology_host_info PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_hostinfo_group_id FOREIGN KEY (group_id) REFERENCES topology_hostgroup(id),
 +  CONSTRAINT FK_hostinfo_host_id FOREIGN KEY (host_id) REFERENCES hosts(host_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_logical_request') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_logical_request (
 +  id BIGINT NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  description VARCHAR(1024),
 +  CONSTRAINT PK_topology_logical_request PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_logicalreq_req_id FOREIGN KEY (request_id) REFERENCES topology_request(id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_host_request') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_host_request (
 +  id BIGINT NOT NULL,
 +  logical_request_id BIGINT NOT NULL,
 +  group_id BIGINT NOT NULL,
 +  stage_id BIGINT NOT NULL,
 +  host_name VARCHAR(255),
 +  CONSTRAINT PK_topology_host_request PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_hostreq_group_id FOREIGN KEY (group_id) REFERENCES topology_hostgroup(id),
 +  CONSTRAINT FK_hostreq_logicalreq_id FOREIGN KEY (logical_request_id) REFERENCES topology_logical_request(id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_host_task') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_host_task (
 +  id BIGINT NOT NULL,
 +  host_request_id BIGINT NOT NULL,
 +  type VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_topology_host_task PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_hosttask_req_id FOREIGN KEY (host_request_id) REFERENCES topology_host_request (id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('topology_logical_task') AND type = 'U')
 +BEGIN
 +CREATE TABLE topology_logical_task (
 +  id BIGINT NOT NULL,
 +  host_task_id BIGINT NOT NULL,
 +  physical_task_id BIGINT,
 +  component VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_topology_logical_task PRIMARY KEY CLUSTERED (id),
 +  CONSTRAINT FK_ltask_hosttask_id FOREIGN KEY (host_task_id) REFERENCES topology_host_task (id),
 +  CONSTRAINT FK_ltask_hrc_id FOREIGN KEY (physical_task_id) REFERENCES host_role_command (task_id))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('setting') AND type = 'U')
 +BEGIN
 +CREATE TABLE setting (
 +  id BIGINT NOT NULL,
 +  name VARCHAR(255) NOT NULL UNIQUE,
 +  setting_type VARCHAR(255) NOT NULL,
 +  content TEXT NOT NULL,
 +  updated_by VARCHAR(255) NOT NULL DEFAULT '_db',
 +  update_timestamp BIGINT NOT NULL,
 +  CONSTRAINT PK_setting PRIMARY KEY (id)
 +)
 +END
 +
 +
 +-- Remote Cluster table
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('remoteambaricluster') AND type = 'U')
 +BEGIN
 +CREATE TABLE remoteambaricluster(
 +  cluster_id BIGINT NOT NULL,
 +  name VARCHAR(255) NOT NULL,
 +  username VARCHAR(255) NOT NULL,
 +  url VARCHAR(255) NOT NULL,
 +  password VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
 +  CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name))
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('remoteambariclusterservice') AND type = 'U')
 +BEGIN
 +CREATE TABLE remoteambariclusterservice(
 +  id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id),
 +  CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id)
 +)
 +END
 +
 +
 +-- Remote Cluster table ends
 +
 +-- upgrade tables
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('upgrade') AND type = 'U')
 +BEGIN
 +CREATE TABLE upgrade (
 +  upgrade_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  request_id BIGINT NOT NULL,
 +  direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
 +  orchestration VARCHAR(255) DEFAULT 'STANDARD' NOT NULL,
 +  upgrade_package VARCHAR(255) NOT NULL,
 +  upgrade_type VARCHAR(32) NOT NULL,
 +  repo_version_id BIGINT NOT NULL,
 +  skip_failures BIT NOT NULL DEFAULT 0,
 +  skip_sc_failures BIT NOT NULL DEFAULT 0,
 +  downgrade_allowed BIT NOT NULL DEFAULT 1,
 +  revert_allowed BIT NOT NULL DEFAULT 0,
 +  suspended BIT DEFAULT 0 NOT NULL,
 +  CONSTRAINT PK_upgrade PRIMARY KEY CLUSTERED (upgrade_id),
 +  FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
 +  FOREIGN KEY (request_id) REFERENCES request(request_id),
 +  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('upgrade_group') AND type = 'U')
 +BEGIN
 +CREATE TABLE upgrade_group (
 +  upgrade_group_id BIGINT NOT NULL,
 +  upgrade_id BIGINT NOT NULL,
 +  group_name VARCHAR(255) DEFAULT '' NOT NULL,
 +  group_title VARCHAR(1024) DEFAULT '' NOT NULL,
 +  CONSTRAINT PK_upgrade_group PRIMARY KEY CLUSTERED (upgrade_group_id),
 +  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('upgrade_item') AND type = 'U')
 +BEGIN
 +CREATE TABLE upgrade_item (
 +  upgrade_item_id BIGINT NOT NULL,
 +  upgrade_group_id BIGINT NOT NULL,
 +  stage_id BIGINT NOT NULL,
 +  state VARCHAR(255) DEFAULT 'NONE' NOT NULL,
 +  hosts TEXT,
 +  tasks TEXT,
 +  item_text TEXT,
 +  CONSTRAINT PK_upgrade_item PRIMARY KEY CLUSTERED (upgrade_item_id),
 +  FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('upgrade_history') AND type = 'U')
 +BEGIN
 +CREATE TABLE upgrade_history(
 +  id BIGINT NOT NULL,
 +  upgrade_id BIGINT NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  component_name VARCHAR(255) NOT NULL,
 +  from_repo_version_id BIGINT NOT NULL,
 +  target_repo_version_id BIGINT NOT NULL,
 +  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
 +  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
 +  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
 +  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
 +  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('servicecomponent_version') AND type = 'U')
 +BEGIN
 +CREATE TABLE servicecomponent_version(
 +  id BIGINT NOT NULL,
 +  component_id BIGINT NOT NULL,
 +  repo_version_id BIGINT NOT NULL,
 +  state VARCHAR(32) NOT NULL,
 +  user_name VARCHAR(255) NOT NULL,
 +  CONSTRAINT PK_sc_version PRIMARY KEY (id),
 +  CONSTRAINT FK_scv_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
 +  CONSTRAINT FK_scv_repo_version_id FOREIGN KEY (repo_version_id) REFERENCES repo_version (repo_version_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('ambari_operation_history') AND type = 'U')
 +BEGIN
 +CREATE TABLE ambari_operation_history(
 +  id BIGINT NOT NULL,
 +  from_version VARCHAR(255) NOT NULL,
 +  to_version VARCHAR(255) NOT NULL,
 +  start_time BIGINT NOT NULL,
 +  end_time BIGINT,
 +  operation_type VARCHAR(255) NOT NULL,
 +  comments TEXT,
 +  CONSTRAINT PK_ambari_operation_history PRIMARY KEY (id)
 +)
 +END
 +
 +
 +
 +-- tasks indices --
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_stage_request_id')
 +BEGIN
 +CREATE INDEX idx_stage_request_id ON stage (request_id)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_hrc_request_id')
 +BEGIN
 +CREATE INDEX idx_hrc_request_id ON host_role_command (request_id)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_hrc_status_role')
 +BEGIN
 +CREATE INDEX idx_hrc_status_role ON host_role_command (status, role)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_rsc_request_id')
 +BEGIN
 +CREATE INDEX idx_rsc_request_id ON role_success_criteria (request_id)
 +END
 +
 +
 +
 +-- altering tables by creating unique constraints----------
 +--------altering tables to add constraints----------
 +
 +-- altering tables by creating foreign keys----------
 +-- Note, Oracle has a limitation of 32 chars in the FK name, and we should use the same FK name in all DB types.
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('FK_clusters_upgrade_id') AND type = 'F')
 +BEGIN
 +ALTER TABLE clusters ADD CONSTRAINT FK_clusters_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id)
 +END
 +
 +
 +-- Kerberos
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('kerberos_principal') AND type = 'U')
 +BEGIN
 +CREATE TABLE kerberos_principal (
 +  principal_name VARCHAR(255) NOT NULL,
 +  is_service SMALLINT NOT NULL DEFAULT 1,
 +  cached_keytab_path VARCHAR(255),
 +  CONSTRAINT PK_kerberos_principal PRIMARY KEY CLUSTERED (principal_name)
 +)
 +END
 +
 +
++IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('kerberos_keytab') AND type = 'U')
++BEGIN
++CREATE TABLE kerberos_keytab (
++  keytab_path VARCHAR(255) NOT NULL,
++  CONSTRAINT PK_krb_keytab_path_host_id PRIMARY KEY CLUSTERED (keytab_path)
++)
++END
++
++
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('kerberos_principal_host') AND type = 'U')
 +BEGIN
 +CREATE TABLE kerberos_principal_host (
 +  principal_name VARCHAR(255) NOT NULL,
++  keytab_path VARCHAR(255) NOT NULL,
++  is_distributed SMALLINT NOT NULL DEFAULT 0,
 +  host_id BIGINT NOT NULL,
-   CONSTRAINT PK_kerberos_principal_host PRIMARY KEY CLUSTERED (principal_name, host_id),
++  CONSTRAINT PK_kerberos_principal_host PRIMARY KEY CLUSTERED (principal_name, keytab_path, host_id),
 +  CONSTRAINT FK_krb_pr_host_id FOREIGN KEY (host_id) REFERENCES hosts (host_id),
-   CONSTRAINT FK_krb_pr_host_principalname FOREIGN KEY (principal_name) REFERENCES kerberos_principal (principal_name))
++  CONSTRAINT FK_krb_pr_host_principalname FOREIGN KEY (principal_name) REFERENCES kerberos_principal (principal_name),
++  CONSTRAINT FK_krb_pr_host_keytab_path FOREIGN KEY (keytab_path) REFERENCES kerberos_keytab (keytab_path)
++)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('kerberos_descriptor') AND type = 'U')
 +BEGIN
 +CREATE TABLE kerberos_descriptor
 +(
 +   kerberos_descriptor_name   VARCHAR(255) NOT NULL,
 +   kerberos_descriptor        VARCHAR(MAX) NOT NULL,
 +   CONSTRAINT PK_kerberos_descriptor PRIMARY KEY (kerberos_descriptor_name)
 +)
 +END
 +
 +
 +-- Kerberos (end)
 +
 +-- Alerting Framework
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_definition') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_definition (
 +  definition_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  definition_name VARCHAR(255) NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  component_name VARCHAR(255),
 +  scope VARCHAR(255) DEFAULT 'ANY' NOT NULL,
 +  label VARCHAR(255),
 +  help_url VARCHAR(512),
 +  description TEXT,
 +  enabled SMALLINT DEFAULT 1 NOT NULL,
 +  schedule_interval INTEGER NOT NULL,
 +  source_type VARCHAR(255) NOT NULL,
 +  alert_source TEXT NOT NULL,
 +  hash VARCHAR(64) NOT NULL,
 +  ignore_host SMALLINT DEFAULT 0 NOT NULL,
 +  repeat_tolerance INTEGER DEFAULT 1 NOT NULL,
 +  repeat_tolerance_enabled SMALLINT DEFAULT 0 NOT NULL,
 +  CONSTRAINT PK_alert_definition PRIMARY KEY CLUSTERED (definition_id),
 +  FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
 +  CONSTRAINT uni_alert_def_name UNIQUE(cluster_id,definition_name)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_history') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_history (
 +  alert_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  alert_definition_id BIGINT NOT NULL,
 +  service_name VARCHAR(255) NOT NULL,
 +  component_name VARCHAR(255),
 +  host_name VARCHAR(255),
 +  alert_instance VARCHAR(255),
 +  alert_timestamp BIGINT NOT NULL,
 +  alert_label VARCHAR(1024),
 +  alert_state VARCHAR(255) NOT NULL,
 +  alert_text TEXT,
 +  CONSTRAINT PK_alert_history PRIMARY KEY CLUSTERED (alert_id),
 +  FOREIGN KEY (alert_definition_id) REFERENCES alert_definition(definition_id),
 +  FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_current') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_current (
 +  alert_id BIGINT NOT NULL,
 +  definition_id BIGINT NOT NULL,
 +  history_id BIGINT NOT NULL UNIQUE,
 +  maintenance_state VARCHAR(255) NOT NULL,
 +  original_timestamp BIGINT NOT NULL,
 +  latest_timestamp BIGINT NOT NULL,
 +  latest_text TEXT,
 +  occurrences BIGINT NOT NULL DEFAULT 1,
 +  firmness VARCHAR(255) NOT NULL DEFAULT 'HARD',
 +  CONSTRAINT PK_alert_current PRIMARY KEY CLUSTERED (alert_id),
 +  FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
 +  FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_group') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_group (
 +  group_id BIGINT NOT NULL,
 +  cluster_id BIGINT NOT NULL,
 +  group_name VARCHAR(255) NOT NULL,
 +  is_default SMALLINT NOT NULL DEFAULT 0,
 +  service_name VARCHAR(255),
 +  CONSTRAINT PK_alert_group PRIMARY KEY CLUSTERED (group_id),
 +  CONSTRAINT uni_alert_group_name UNIQUE(cluster_id,group_name)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_target') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_target (
 +  target_id BIGINT NOT NULL,
 +  target_name VARCHAR(255) NOT NULL UNIQUE,
 +  notification_type VARCHAR(64) NOT NULL,
 +  properties TEXT,
 +  description VARCHAR(1024),
 +  is_global SMALLINT NOT NULL DEFAULT 0,
 +  is_enabled SMALLINT NOT NULL DEFAULT 1,
 +  CONSTRAINT PK_alert_target PRIMARY KEY CLUSTERED (target_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_target_states') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_target_states (
 +  target_id BIGINT NOT NULL,
 +  alert_state VARCHAR(255) NOT NULL,
 +  FOREIGN KEY (target_id) REFERENCES alert_target(target_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_group_target') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_group_target (
 +  group_id BIGINT NOT NULL,
 +  target_id BIGINT NOT NULL,
 +  CONSTRAINT PK_alert_group_target PRIMARY KEY CLUSTERED (group_id, target_id),
 +  FOREIGN KEY (group_id) REFERENCES alert_group(group_id),
 +  FOREIGN KEY (target_id) REFERENCES alert_target(target_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_grouping') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_grouping (
 +  definition_id BIGINT NOT NULL,
 +  group_id BIGINT NOT NULL,
 +  CONSTRAINT PK_alert_grouping PRIMARY KEY CLUSTERED (group_id, definition_id),
 +  FOREIGN KEY (definition_id) REFERENCES alert_definition(definition_id),
 +  FOREIGN KEY (group_id) REFERENCES alert_group(group_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('alert_notice') AND type = 'U')
 +BEGIN
 +CREATE TABLE alert_notice (
 +  notification_id BIGINT NOT NULL,
 +  target_id BIGINT NOT NULL,
 +  history_id BIGINT NOT NULL,
 +  notify_state VARCHAR(255) NOT NULL,
 +  uuid VARCHAR(64) NOT NULL UNIQUE,
 +  CONSTRAINT PK_alert_notice PRIMARY KEY CLUSTERED (notification_id),
 +  FOREIGN KEY (target_id) REFERENCES alert_target(target_id),
 +  FOREIGN KEY (history_id) REFERENCES alert_history(alert_id)
 +)
 +END
 +
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_history_def_id')
 +BEGIN
 +CREATE INDEX idx_alert_history_def_id on alert_history(alert_definition_id)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_history_service')
 +BEGIN
 +CREATE INDEX idx_alert_history_service on alert_history(service_name)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_history_host')
 +BEGIN
 +CREATE INDEX idx_alert_history_host on alert_history(host_name)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_history_time')
 +BEGIN
 +CREATE INDEX idx_alert_history_time on alert_history(alert_timestamp)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_history_state')
 +BEGIN
 +CREATE INDEX idx_alert_history_state on alert_history(alert_state)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_group_name')
 +BEGIN
 +CREATE INDEX idx_alert_group_name on alert_group(group_name)
 +END
 +
 +IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'idx_alert_notice_state')
 +BEGIN
 +CREATE INDEX idx_alert_notice_state on alert_notice(notify_state)
 +END
 +
 +
 +---------inserting some data-----------
 +BEGIN TRANSACTION
 +  DELETE metainfo;
 +  DELETE adminprivilege;
 +  DELETE permission_roleauthorization;
 +  DELETE roleauthorization;
 +  DELETE adminpermission;
 +  DELETE users;
 +  DELETE adminprincipal;
 +  DELETE adminprincipaltype;
 +  DELETE adminresource;
 +  DELETE adminresourcetype;
 +  DELETE ambari_sequences;
 +  INSERT INTO ambari_sequences (sequence_name, [sequence_value])
 +  VALUES
 +    ('cluster_id_seq', 1),
 +    ('host_id_seq', 0),
 +    ('user_id_seq', 2),
 +    ('group_id_seq', 1),
 +    ('member_id_seq', 1),
 +    ('host_role_command_id_seq', 1),
 +    ('configgroup_id_seq', 1),
 +    ('requestschedule_id_seq', 1),
 +    ('resourcefilter_id_seq', 1),
 +    ('viewentity_id_seq', 0),
 +    ('operation_level_id_seq', 1),
 +    ('view_instance_id_seq', 1),
 +    ('resource_type_id_seq', 4),
 +    ('resource_id_seq', 2),
 +    ('principal_type_id_seq', 8),
 +    ('principal_id_seq', 13),
 +    ('permission_id_seq', 7),
 +    ('privilege_id_seq', 1),
 +    ('alert_definition_id_seq', 0),
 +    ('alert_group_id_seq', 0),
 +    ('alert_target_id_seq', 0),
 +    ('alert_history_id_seq', 0),
 +    ('alert_notice_id_seq', 0),
 +    ('alert_current_id_seq', 0),
 +    ('config_id_seq', 11),
 +    ('repo_version_id_seq', 0),
 +    ('host_version_id_seq', 0),
 +    ('service_config_id_seq', 1),
 +    ('upgrade_id_seq', 0),
 +    ('upgrade_group_id_seq', 0),
 +    ('widget_id_seq', 0),
 +    ('widget_layout_id_seq', 0),
 +    ('upgrade_item_id_seq', 0),
 +    ('stack_id_seq', 0),
 +    ('extension_id_seq', 0),
 +    ('link_id_seq', 0),
 +    ('topology_host_info_id_seq', 0),
 +    ('topology_host_request_id_seq', 0),
 +    ('topology_host_task_id_seq', 0),
 +    ('topology_logical_request_id_seq', 0),
 +    ('topology_logical_task_id_seq', 0),
 +    ('topology_request_id_seq', 0),
 +    ('topology_host_group_id_seq', 0),
 +    ('setting_id_seq', 0),
 +    ('hostcomponentstate_id_seq', 0),
 +    ('servicecomponentdesiredstate_id_seq', 0),
 +    ('upgrade_history_id_seq', 0),
 +    ('blueprint_setting_id_seq', 0),
 +    ('ambari_operation_history_id_seq', 0),
 +    ('remote_cluster_id_seq', 0),
 +    ('remote_cluster_service_id_seq', 0),
 +    ('servicecomponent_version_id_seq', 0),
 +    ('hostcomponentdesiredstate_id_seq', 0)
 +
 +  insert into adminresourcetype (resource_type_id, resource_type_name)
 +  values
 +    (1, 'AMBARI'),
 +    (2, 'CLUSTER'),
 +    (3, 'VIEW')
 +
 +  insert into adminresource (resource_id, resource_type_id)
 +    select 1, 1
 +
 +  insert into adminprincipaltype (principal_type_id, principal_type_name)
 +  values
 +    (1, 'USER'),
 +    (2, 'GROUP'),
 +    (8, 'ROLE')
 +
 +  insert into adminprincipal (principal_id, principal_type_id)
 +  values
 +    (1, 1),
 +    (7, 8),
 +    (8, 8),
 +    (9, 8),
 +    (10, 8),
 +    (11, 8),
 +    (12, 8),
 +    (13, 8)
 +
 +  insert into users(user_id, principal_id, user_name, user_password)
 +    select 1, 1, 'admin','538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00'
 +
 +  insert into adminpermission(permission_id, permission_name, resource_type_id, permission_label, principal_id, sort_order)
 +  values
 +    (1, 'AMBARI.ADMINISTRATOR', 1, 'Ambari Administrator', 7, 1),
 +    (2, 'CLUSTER.USER', 2, 'Cluster User', 8, 6),
 +    (3, 'CLUSTER.ADMINISTRATOR', 2, 'Cluster Administrator', 9, 2),
 +    (4, 'VIEW.USER', 3, 'View User', 10, 7),
 +    (5, 'CLUSTER.OPERATOR', 2, 'Cluster Operator', 11, 3),
 +    (6, 'SERVICE.ADMINISTRATOR', 2, 'Service Administrator', 12, 4),
 +    (7, 'SERVICE.OPERATOR', 2, 'Service Operator', 13, 5)
 +
 +  INSERT INTO roleauthorization(authorization_id, authorization_name)
 +    SELECT 'VIEW.USE', 'Use View' UNION ALL
 +    SELECT 'SERVICE.VIEW_METRICS', 'View metrics' UNION ALL
 +    SELECT 'SERVICE.VIEW_STATUS_INFO', 'View status information' UNION ALL
 +    SELECT 'SERVICE.VIEW_CONFIGS', 'View configurations' UNION ALL
 +    SELECT 'SERVICE.COMPARE_CONFIGS', 'Compare configurations' UNION ALL
 +    SELECT 'SERVICE.VIEW_ALERTS', 'View service-level alerts' UNION ALL
 +    SELECT 'SERVICE.START_STOP', 'Start/Stop/Restart Service' UNION ALL
 +    SELECT 'SERVICE.DECOMMISSION_RECOMMISSION', 'Decommission/recommission' UNION ALL
 +    SELECT 'SERVICE.RUN_SERVICE_CHECK', 'Run service checks' UNION ALL
 +    SELECT 'SERVICE.TOGGLE_MAINTENANCE', 'Turn on/off maintenance mode' UNION ALL
 +    SELECT 'SERVICE.RUN_CUSTOM_COMMAND', 'Perform service-specific tasks' UNION ALL
 +    SELECT 'SERVICE.MODIFY_CONFIGS', 'Modify configurations' UNION ALL
 +    SELECT 'SERVICE.MANAGE_ALERTS', 'Manage service-level alerts' UNION ALL
 +    SELECT 'SERVICE.MANAGE_CONFIG_GROUPS', 'Manage configuration groups' UNION ALL
 +    SELECT 'SERVICE.MOVE', 'Move service to another host' UNION ALL
 +    SELECT 'SERVICE.ENABLE_HA', 'Enable HA' UNION ALL
 +    SELECT 'SERVICE.TOGGLE_ALERTS', 'Enable/disable service-level alerts' UNION ALL
 +    SELECT 'SERVICE.ADD_DELETE_SERVICES', 'Add/delete services' UNION ALL
 +    SELECT 'SERVICE.VIEW_OPERATIONAL_LOGS', 'View service operational logs' UNION ALL
 +    SELECT 'SERVICE.SET_SERVICE_USERS_GROUPS', 'Set service users and groups' UNION ALL
 +    SELECT 'SERVICE.MANAGE_AUTO_START', 'Manage service auto-start' UNION ALL
 +    SELECT 'HOST.VIEW_METRICS', 'View metrics' UNION ALL
 +    SELECT 'HOST.VIEW_STATUS_INFO', 'View status information' UNION ALL
 +    SELECT 'HOST.VIEW_CONFIGS', 'View configuration' UNION ALL
 +    SELECT 'HOST.TOGGLE_MAINTENANCE', 'Turn on/off maintenance mode' UNION ALL
 +    SELECT 'HOST.ADD_DELETE_COMPONENTS', 'Install components' UNION ALL
 +    SELECT 'HOST.ADD_DELETE_HOSTS', 'Add/Delete hosts' UNION ALL
 +    SELECT 'CLUSTER.VIEW_METRICS', 'View metrics' UNION ALL
 +    SELECT 'CLUSTER.VIEW_STATUS_INFO', 'View status information' UNION ALL
 +    SELECT 'CLUSTER.VIEW_CONFIGS', 'View configuration' UNION ALL
 +    SELECT 'CLUSTER.VIEW_STACK_DETAILS', 'View stack version details' UNION ALL
 +    SELECT 'CLUSTER.VIEW_ALERTS', 'View cluster-level alerts' UNION ALL
 +    SELECT 'CLUSTER.MANAGE_CREDENTIALS', 'Manage external credentials' UNION ALL
 +    SELECT 'CLUSTER.MODIFY_CONFIGS', 'Modify cluster configurations' UNION ALL
 +    SELECT 'CLUSTER.MANAGE_ALERTS', 'Manage cluster-level alerts' UNION ALL
 +    SELECT 'CLUSTER.MANAGE_USER_PERSISTED_DATA', 'Manage cluster-level user persisted data' UNION ALL
 +    SELECT 'CLUSTER.TOGGLE_ALERTS', 'Enable/disable cluster-level alerts' UNION ALL
 +    SELECT 'CLUSTER.MANAGE_CONFIG_GROUPS', 'Manage cluster config groups' UNION ALL
 +    SELECT 'CLUSTER.TOGGLE_KERBEROS', 'Enable/disable Kerberos' UNION ALL
 +    SELECT 'CLUSTER.UPGRADE_DOWNGRADE_STACK', 'Upgrade/downgrade stack' UNION ALL
 +    SELECT 'CLUSTER.RUN_CUSTOM_COMMAND', 'Perform custom cluster-level actions' UNION ALL
 +    SELECT 'CLUSTER.MANAGE_AUTO_START', 'Manage service auto-start configuration' UNION ALL
 +    SELECT 'CLUSTER.MANAGE_ALERT_NOTIFICATIONS', 'Manage alert notifications configuration' UNION ALL
 +    SELECT 'AMBARI.ADD_DELETE_CLUSTERS', 'Create new clusters' UNION ALL
 +    SELECT 'AMBARI.RENAME_CLUSTER', 'Rename clusters' UNION ALL
 +    SELECT 'AMBARI.MANAGE_SETTINGS', 'Manage settings' UNION ALL
++    SELECT 'AMBARI.MANAGE_CONFIGURATION', 'Manage ambari configuration' UNION ALL
 +    SELECT 'AMBARI.MANAGE_USERS', 'Manage users' UNION ALL
 +    SELECT 'AMBARI.MANAGE_GROUPS', 'Manage groups' UNION ALL
 +    SELECT 'AMBARI.MANAGE_VIEWS', 'Manage Ambari Views' UNION ALL
 +    SELECT 'AMBARI.ASSIGN_ROLES', 'Assign roles' UNION ALL
 +    SELECT 'AMBARI.MANAGE_STACK_VERSIONS', 'Manage stack versions' UNION ALL
 +    SELECT 'AMBARI.EDIT_STACK_REPOS', 'Edit stack repository URLs' UNION ALL
 +    SELECT 'AMBARI.RUN_CUSTOM_COMMAND', 'Perform custom administrative actions'
 +
 +  -- Set authorizations for View User role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'VIEW.USE' FROM adminpermission WHERE permission_name='VIEW.USER'
 +
 +  -- Set authorizations for Cluster User role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'SERVICE.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'SERVICE.COMPARE_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.USER' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.USER'
 +
 +  -- Set authorizations for Service Operator role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'SERVICE.VIEW_METRICS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.COMPARE_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_ALERTS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.START_STOP' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.DECOMMISSION_RECOMMISSION' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_SERVICE_CHECK' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_CUSTOM_COMMAND' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_METRICS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_METRICS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='SERVICE.OPERATOR'
 +
 +  -- Set authorizations for Service Administrator role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'SERVICE.VIEW_METRICS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.COMPARE_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_ALERTS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.START_STOP' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.DECOMMISSION_RECOMMISSION' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_SERVICE_CHECK' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_CUSTOM_COMMAND' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_OPERATIONAL_LOGS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_AUTO_START' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_METRICS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_METRICS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='SERVICE.ADMINISTRATOR'
 +
 +  -- Set authorizations for Cluster Operator role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'SERVICE.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.COMPARE_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.START_STOP' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.DECOMMISSION_RECOMMISSION' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_SERVICE_CHECK' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_CUSTOM_COMMAND' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MOVE' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.ENABLE_HA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_OPERATIONAL_LOGS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_AUTO_START' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.ADD_DELETE_COMPONENTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'HOST.ADD_DELETE_HOSTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_AUTO_START' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'
 +
 +  -- Set authorizations for Cluster Administrator role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'SERVICE.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.COMPARE_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.START_STOP' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.DECOMMISSION_RECOMMISSION' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_SERVICE_CHECK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_CUSTOM_COMMAND' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MOVE' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.ENABLE_HA' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.ADD_DELETE_SERVICES' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_OPERATIONAL_LOGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.SET_SERVICE_USERS_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_AUTO_START' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.ADD_DELETE_COMPONENTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.ADD_DELETE_HOSTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_METRICS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.UPGRADE_DOWNGRADE_STACK' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_AUTO_START' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_ALERT_NOTIFICATIONS' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.RUN_CUSTOM_COMMAND' FROM adminpermission WHERE permission_name='CLUSTER.ADMINISTRATOR'
 +
 +  -- Set authorizations for Administrator role
 +  INSERT INTO permission_roleauthorization(permission_id, authorization_id)
 +    SELECT permission_id, 'VIEW.USE' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_METRICS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.COMPARE_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.START_STOP' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.DECOMMISSION_RECOMMISSION' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_SERVICE_CHECK' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.RUN_CUSTOM_COMMAND' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MOVE' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.ENABLE_HA' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.ADD_DELETE_SERVICES' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.VIEW_OPERATIONAL_LOGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.SET_SERVICE_USERS_GROUPS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'SERVICE.MANAGE_AUTO_START' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_METRICS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.TOGGLE_MAINTENANCE' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.ADD_DELETE_COMPONENTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'HOST.ADD_DELETE_HOSTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_METRICS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STATUS_INFO' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MODIFY_CONFIGS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.TOGGLE_ALERTS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL
 +    SELECT permission_id, 'CLUSTER.TOGGLE_KERBEROS' FROM adminpermission WHERE permission_name='AMBARI.ADMINISTRATOR' UNION ALL


<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ambari/blob/366f6ca9/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------


[19/50] [abbrv] ambari git commit: AMBARI-22529. PERF stack fixes (aonishuk)

Posted by ao...@apache.org.
AMBARI-22529. PERF stack fixes (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/530f1d5e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/530f1d5e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/530f1d5e

Branch: refs/heads/branch-3.0-perf
Commit: 530f1d5e34eb5eb5e3e509bd9934a590bed64ac9
Parents: b832f70
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Tue Nov 28 15:30:10 2017 +0200
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Tue Nov 28 15:30:10 2017 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/ambari/server/state/ServiceInfo.java | 2 +-
 .../stacks/PERF/1.0/hooks/before-INSTALL/scripts/hook.py      | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/530f1d5e/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
index f1c63bf..c0342eb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
@@ -87,7 +87,7 @@ public class ServiceInfo implements Validable{
     JAVA
   }
   @XmlElement(name="service_advisor_type")
-  private ServiceAdvisorType serviceAdvisorType = null;
+  private ServiceAdvisorType serviceAdvisorType = ServiceAdvisorType.PYTHON;
 
   @XmlTransient
   private List<PropertyInfo> properties;

http://git-wip-us.apache.org/repos/asf/ambari/blob/530f1d5e/ambari-server/src/main/resources/stacks/PERF/1.0/hooks/before-INSTALL/scripts/hook.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/PERF/1.0/hooks/before-INSTALL/scripts/hook.py b/ambari-server/src/main/resources/stacks/PERF/1.0/hooks/before-INSTALL/scripts/hook.py
index 833fdbc..513b994 100644
--- a/ambari-server/src/main/resources/stacks/PERF/1.0/hooks/before-INSTALL/scripts/hook.py
+++ b/ambari-server/src/main/resources/stacks/PERF/1.0/hooks/before-INSTALL/scripts/hook.py
@@ -23,6 +23,7 @@ from resource_management.core.resources.system import Directory, File, Execute
 from resource_management.libraries.script import Hook
 
 AMBARI_AGENT_CACHE_DIR = 'AMBARI_AGENT_CACHE_DIR'
+DEFAULT_AMBARI_AGENT_CACHE_DIR = '/var/lib/ambari-agent/cache/'
 
 BEFORE_INSTALL_SCRIPTS = "hooks/before-INSTALL/scripts"
 STACK = "PERF/1.0"
@@ -38,6 +39,12 @@ class BeforeInstallHook(Hook):
     self.run_custom_hook('before-ANY')
     print "Before Install Hook"
     cache_dir = self.extrakt_var_from_pythonpath(AMBARI_AGENT_CACHE_DIR)
+
+    # this happens if PythonExecutor.py.sed hack was not done.
+    if not cache_dir:
+      print "WARN: Cache dir for the agent could not be detected. Using default cache dir"
+      cache_dir = DEFAULT_AMBARI_AGENT_CACHE_DIR
+
     conf_select = os.path.join(cache_dir, CONF_SELECT_PY)
     dist_select = os.path.join(cache_dir, DISTRO_SELECT_PY)
     try:


[43/50] [abbrv] ambari git commit: AMBARI-22490. Uploading a Zero KB file to HDFS via File View Fails (pallavkul)

Posted by ao...@apache.org.
AMBARI-22490. Uploading a Zero KB file to HDFS via File View Fails (pallavkul)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ff08592a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ff08592a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ff08592a

Branch: refs/heads/branch-3.0-perf
Commit: ff08592a32d3b8bf4c2ba2c674b73233c775f424
Parents: ca174fb
Author: pallavkul <pa...@gmail.com>
Authored: Thu Nov 30 07:16:47 2017 +0530
Committer: pallavkul <pa...@gmail.com>
Committed: Thu Nov 30 07:16:47 2017 +0530

----------------------------------------------------------------------
 .../resources/ui/app/components/upload-file.js  | 38 ++++++++++----------
 1 file changed, 19 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ff08592a/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
----------------------------------------------------------------------
diff --git a/contrib/views/files/src/main/resources/ui/app/components/upload-file.js b/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
index 8a14272..1a5e911 100644
--- a/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
+++ b/contrib/views/files/src/main/resources/ui/app/components/upload-file.js
@@ -104,25 +104,25 @@ export default Ember.Component.extend(OperationModal, {
           url: url
         });
         this.set('uploader', uploader);
-        if(!Ember.isEmpty(file)) {
-          uploader.upload(file, {path: this.get('path')});
-          this.setUploading(file.name);
-          uploader.on('progress', (e) => {
-            this.setUploadPercent(e.percent);
-          });
-          uploader.on('didUpload', (e) => {
-            this.set('uploader');
-            this.send('close');
-            this.sendAction('refreshAction');
-          });
-          uploader.on('didError', (jqXHR, textStatus, errorThrown) => {
-            var error = Ember.$.parseJSON(jqXHR.responseText);
-            this.set('uploader');
-            this.get('logger').danger(`Failed to upload ${file.name} to ${this.get('path')}`, error);
-            this.send('close');
-            return false;
-          });
-        }
+        uploader.upload(file, {
+          path: this.get('path')
+        });
+        this.setUploading(file.name);
+        uploader.on('progress', (e) => {
+          this.setUploadPercent(e.percent);
+        });
+        uploader.on('didUpload', (e) => {
+          this.set('uploader');
+          this.send('close');
+          this.sendAction('refreshAction');
+        });
+        uploader.on('didError', (jqXHR, textStatus, errorThrown) => {
+          var error = Ember.$.parseJSON(jqXHR.responseText);
+          this.set('uploader');
+          this.get('logger').danger(`Failed to upload ${file.name} to ${this.get('path')}`, error);
+          this.send('close');
+          return false;
+        });
       }, (error) => {
         console.error("Cannot add a directory.", error);
         this.send('close');


[40/50] [abbrv] ambari git commit: AMBARI-22543. Log Search: backend should not return with 302 redirect if authentication fails (oleewere)

Posted by ao...@apache.org.
AMBARI-22543. Log Search: backend should not return with 302 redirect if authentication fails (oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0d7f6096
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0d7f6096
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0d7f6096

Branch: refs/heads/branch-3.0-perf
Commit: 0d7f60961fba7c5706ef3d79a7d9507d097fab6e
Parents: f6fd9b5
Author: Oliver Szabo <ol...@gmail.com>
Authored: Wed Nov 29 14:08:00 2017 +0100
Committer: Oliver Szabo <ol...@gmail.com>
Committed: Wed Nov 29 17:38:35 2017 +0100

----------------------------------------------------------------------
 .../filters/LogsearchAuthenticationEntryPoint.java   | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/0d7f6096/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchAuthenticationEntryPoint.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchAuthenticationEntryPoint.java b/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchAuthenticationEntryPoint.java
index 2fe5f7b..b1ceb3a 100644
--- a/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchAuthenticationEntryPoint.java
+++ b/ambari-logsearch/ambari-logsearch-server/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchAuthenticationEntryPoint.java
@@ -24,12 +24,13 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
 
 public class LogsearchAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
-  private static final Logger logger = Logger.getLogger(LogsearchAuthenticationEntryPoint.class);
+  private static final Logger logger = LoggerFactory.getLogger(LogsearchAuthenticationEntryPoint.class);
 
   public LogsearchAuthenticationEntryPoint(String loginFormUrl) {
     super(loginFormUrl);
@@ -38,13 +39,7 @@ public class LogsearchAuthenticationEntryPoint extends LoginUrlAuthenticationEnt
   @Override
   public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
     throws IOException, ServletException {
-    String ajaxRequestHeader = request.getHeader("X-Requested-With");
-    if (ajaxRequestHeader != null && ajaxRequestHeader.equalsIgnoreCase("XMLHttpRequest")) {
-      logger.debug("AJAX request. Authentication required. Returning URL=" + request.getRequestURI());
-      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Session Timeout");
-    } else {
-      logger.debug("Redirecting to login page :" + this.getLoginFormUrl());
-      super.commence(request, response, authException);
-    }
+    logger.debug("Got 401 from request: {}", request.getRequestURI());
+    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
   }
 }


[31/50] [abbrv] ambari git commit: AMBARI-22458. SNMP Trap should have sysuptime field filled - checkstyle fix

Posted by ao...@apache.org.
AMBARI-22458. SNMP Trap should have sysuptime field filled - checkstyle fix


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7fd404ad
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7fd404ad
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7fd404ad

Branch: refs/heads/branch-3.0-perf
Commit: 7fd404add302aed0c3d2fe52a6ddacb957a992b6
Parents: 31a0f19
Author: Doroszlai, Attila <ad...@hortonworks.com>
Authored: Tue Nov 28 22:37:33 2017 +0100
Committer: Doroszlai, Attila <ad...@hortonworks.com>
Committed: Tue Nov 28 22:37:33 2017 +0100

----------------------------------------------------------------------
 .../notifications/dispatchers/AmbariSNMPDispatcher.java       | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7fd404ad/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
index 8e397ed..f4b2564 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/AmbariSNMPDispatcher.java
@@ -19,6 +19,8 @@
 package org.apache.ambari.server.notifications.dispatchers;
 
 import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
 import java.math.BigDecimal;
 import java.util.Collections;
 import java.util.HashSet;
@@ -36,15 +38,12 @@ import org.snmp4j.mp.SnmpConstants;
 import org.snmp4j.smi.Integer32;
 import org.snmp4j.smi.OID;
 import org.snmp4j.smi.OctetString;
+import org.snmp4j.smi.TimeTicks;
 import org.snmp4j.smi.VariableBinding;
 import org.snmp4j.util.DefaultPDUFactory;
-import org.snmp4j.smi.TimeTicks;
 
 import com.google.inject.Singleton;
 
-import java.lang.management.RuntimeMXBean;
-import java.lang.management.ManagementFactory;
-
 /**
  * The {@link AmbariSNMPDispatcher} class is used to dispatch {@link AlertNotification} via SNMP using predefined Ambari OIDs.
  *


[29/50] [abbrv] ambari git commit: AMBARI-22527 : Error while viewing topology details - Storm View (Sanket Shah via mradhakrishnan)

Posted by ao...@apache.org.
AMBARI-22527 : Error while viewing topology details - Storm View (Sanket Shah via mradhakrishnan)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/11d7a6ad
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/11d7a6ad
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/11d7a6ad

Branch: refs/heads/branch-3.0-perf
Commit: 11d7a6ad7a1c7070e87069d5183acfeb68fe6ab9
Parents: aa652af
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Authored: Tue Nov 28 10:34:26 2017 -0800
Committer: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Committed: Tue Nov 28 10:34:26 2017 -0800

----------------------------------------------------------------------
 .../scripts/containers/ComponentDetailView.jsx  |  2 +-
 .../storm/src/main/resources/ui/package.json    | 20 ++++++++++----------
 2 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/11d7a6ad/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ComponentDetailView.jsx
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ComponentDetailView.jsx b/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ComponentDetailView.jsx
index 2b3ed69..a5b356b 100644
--- a/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ComponentDetailView.jsx
+++ b/contrib/views/storm/src/main/resources/ui/app/scripts/containers/ComponentDetailView.jsx
@@ -574,7 +574,7 @@ export default class ComponentDetailView extends Component {
               <div className="form-group">
                 <label className="col-sm-4 control-label">ID:</label>
                 <div className="col-sm-8">
-                  <p className="form-control-static" style={{'word-wrap' : 'break-word'}}>{componentDetail.id}</p>
+                  <p className="form-control-static" style={{'wordWrap' : 'break-word'}}>{componentDetail.id}</p>
                 </div>
               </div>
               <div className="form-group">

http://git-wip-us.apache.org/repos/asf/ambari/blob/11d7a6ad/contrib/views/storm/src/main/resources/ui/package.json
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/ui/package.json b/contrib/views/storm/src/main/resources/ui/package.json
index f9e029b..3b68936 100644
--- a/contrib/views/storm/src/main/resources/ui/package.json
+++ b/contrib/views/storm/src/main/resources/ui/package.json
@@ -66,22 +66,22 @@
     "postcss-loader": "^1.2.2",
     "prop-types": "^15.6.0",
     "react": "15.6.2",
-    "react-bootstrap": "^0.31.3",
-    "react-bootstrap-switch": "^3.4.5",
-    "react-breadcrumbs": "^1.3.16",
-    "react-codemirror": "^0.2.6",
-    "react-datetime": "^2.5.0",
+    "react-bootstrap": "0.31.3",
+    "react-bootstrap-switch": "3.4.5",
+    "react-breadcrumbs": "1.3.16",
+    "react-codemirror": "0.2.6",
+    "react-datetime": "2.5.0",
     "react-dom": "15.6.2",
     "react-hot-loader": "^3.0.0-beta.3",
     "react-onclickoutside": "^5.3.2",
-    "react-router": "^2.6.0",
-    "react-router-bootstrap": "^0.23.1",
-    "react-select": "^1.0.0-beta14",
-    "react-toastr": "^2.8.0",
+    "react-router": "2.6.0",
+    "react-router-bootstrap": "0.23.1",
+    "react-select": "1.0.0-rc.10",
+    "react-toastr": "2.8.0",
     "react-treebeard": "^1.1.4",
     "react-twitter-typeahead": "^1.1.12",
     "react-utils": "^1.0.0",
-    "reactable": "^0.14.0",
+    "reactable": "0.14.0",
     "require-dir": "^0.3.0",
     "run-sequence": "^1.2.2",
     "style-loader": "^0.13.1",


[39/50] [abbrv] ambari git commit: AMBARI-22484. Stack advisor should disallow lzo enable without accepting license agreement. Additional fixes. (mpapirkovskyy)

Posted by ao...@apache.org.
AMBARI-22484. Stack advisor should disallow lzo enable without accepting license agreement. Additional fixes. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e12efe38
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e12efe38
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e12efe38

Branch: refs/heads/branch-3.0-perf
Commit: e12efe38a0cdc6a0e1554026949bfeef60673a5a
Parents: 82692bd
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Wed Nov 29 17:23:49 2017 +0200
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Wed Nov 29 18:30:08 2017 +0200

----------------------------------------------------------------------
 .../stackadvisor/StackAdvisorRequest.java       |  8 +++++
 .../stacks/HDP/2.0.6/services/stack_advisor.py  | 36 +++++++++++++++-----
 .../src/main/resources/stacks/stack_advisor.py  |  9 +++++
 .../stacks/2.0.6/common/test_stack_advisor.py   | 14 ++++++--
 4 files changed, 55 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e12efe38/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
index 62b8d15..b30eec6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
@@ -123,6 +123,9 @@ public class StackAdvisorRequest {
     this.configGroups = configGroups;
   }
 
+  /**
+   * @return true if GPL license is accepted, false otherwise
+   */
   public Boolean getGplLicenseAccepted() {
     return gplLicenseAccepted;
   }
@@ -199,6 +202,11 @@ public class StackAdvisorRequest {
       return this;
     }
 
+    /**
+     * Set GPL license acceptance parameter to request.
+     * @param gplLicenseAccepted is GPL license accepted.
+     * @return stack advisor request builder.
+     */
     public StackAdvisorRequestBuilder withGPLLicenseAccepted(
         Boolean gplLicenseAccepted) {
       this.instance.gplLicenseAccepted = gplLicenseAccepted;

http://git-wip-us.apache.org/repos/asf/ambari/blob/e12efe38/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
index bfa2f5a..5584377 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
@@ -352,20 +352,38 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     self.recommendHadoopProxyUsers(configurations, services, hosts)
 
   def getLZOSupportValidationItems(self, properties, services):
+    '''
+    Checks GPL license is accepted when GPL software is used.
+    :param properties: dict of properties' name and value pairs
+    :param services: list of services
+    :return: NOT_APPLICABLE messages in case GPL license is not accepted
+    '''
     services_list = self.get_services_list(services)
 
+    validations = []
     if "HDFS" in services_list:
       lzo_allowed = services["gpl-license-accepted"]
-      property_name = "io.compression.codec.lzo.class"
-      if property_name in properties:
-        property_value = properties.get(property_name)
-        if not lzo_allowed and "com.hadoop.compression.lzo.LzoCodec" in property_value:
-          return [{"config-name": property_name, "item": self.getErrorItem(
-            "Your Ambari Server has not been configured to download LZO and install it. "
-            "LZO is GPL software and requires you to accept a license prior to use. "
-            "Please refer to this documentation to configure Ambari before proceeding.")}]
 
-    return []
+      self.validatePropertyToLZOCodec("io.compression.codecs", properties, lzo_allowed, validations)
+      self.validatePropertyToLZOCodec("io.compression.codec.lzo.class", properties, lzo_allowed, validations)
+    return validations
+
+  def validatePropertyToLZOCodec(self, property_name, properties, lzo_allowed, validations):
+    '''
+    Checks specified property contains LZO codec class and requires GPL license acceptance.
+    :param property_name: property name
+    :param properties: dict of properties' name and value pairs
+    :param lzo_allowed: is gpl license accepted
+    :param validations: list with validation failures
+    '''
+    lzo_codec_class = "com.hadoop.compression.lzo.LzoCodec"
+    if property_name in properties:
+      property_value = properties.get(property_name)
+      if not lzo_allowed and lzo_codec_class in property_value:
+        validations.append({"config-name": property_name, "item": self.getNotApplicableItem(
+          "Your Ambari Server has not been configured to download LZO and install it. "
+          "LZO is GPL software and requires you to accept a license prior to use. "
+          "Please refer to the documentation to configure Ambari before proceeding.")})
 
   def recommendHbaseConfigurations(self, configurations, clusterData, services, hosts):
     # recommendations for HBase env config

http://git-wip-us.apache.org/repos/asf/ambari/blob/e12efe38/ambari-server/src/main/resources/stacks/stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/stack_advisor.py b/ambari-server/src/main/resources/stacks/stack_advisor.py
index 89f2997..0dcfff8 100644
--- a/ambari-server/src/main/resources/stacks/stack_advisor.py
+++ b/ambari-server/src/main/resources/stacks/stack_advisor.py
@@ -1749,6 +1749,15 @@ class DefaultStackAdvisor(StackAdvisor):
     """
     return {"level": "ERROR", "message": message}
 
+  def getNotApplicableItem(self, message):
+    '''
+    Creates report about validation error that can not be ignored. 
+    UI should not allow the proceeding of work.
+    :param message: error description.
+    :return: report about error.
+    '''
+    return {"level": "NOT_APPLICABLE", "message": message}
+
   def getComponentHostNames(self, servicesDict, serviceName, componentName):
     for service in servicesDict["services"]:
       if service["StackServices"]["service_name"] == serviceName:

http://git-wip-us.apache.org/repos/asf/ambari/blob/e12efe38/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
index 6c774af..300ffe9 100644
--- a/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
+++ b/ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
@@ -2522,7 +2522,8 @@ class TestHDP206StackAdvisor(TestCase):
                   'hadoop.proxyuser.hdfs-user.groups': '*',
                   'hadoop.proxyuser.yarn-user.hosts': 'host1,host2',
                   'hadoop.proxyuser.yarn-user.groups': '*',
-                  'io.compression.codec.lzo.class': 'com.hadoop.compression.lzo.LzoCodec'}
+                  'io.compression.codec.lzo.class': 'com.hadoop.compression.lzo.LzoCodec',
+                  'io.compression.codecs': 'AnotherCodec, com.hadoop.compression.lzo.LzoCodec'}
     services = {
       'services':  [
         { 'StackServices': {'service_name': 'HDFS'}},
@@ -2558,10 +2559,17 @@ class TestHDP206StackAdvisor(TestCase):
     res_expected = [{'config-type': 'core-site',
                      'message': 'Your Ambari Server has not been configured to download LZO and install it. '
                                 'LZO is GPL software and requires you to accept a license prior to use. '
-                                'Please refer to this documentation to configure Ambari before proceeding.',
+                                'Please refer to the documentation to configure Ambari before proceeding.',
+                     'type': 'configuration',
+                     'config-name': 'io.compression.codecs',
+                     'level': 'NOT_APPLICABLE'},
+                    {'config-type': 'core-site',
+                     'message': 'Your Ambari Server has not been configured to download LZO and install it. '
+                                'LZO is GPL software and requires you to accept a license prior to use. '
+                                'Please refer to the documentation to configure Ambari before proceeding.',
                      'type': 'configuration',
                      'config-name': 'io.compression.codec.lzo.class',
-                     'level': 'ERROR'}]
+                     'level': 'NOT_APPLICABLE'}]
 
     res = self.stackAdvisor.validateHDFSConfigurationsCoreSite(properties, {}, configurations, services, hosts)
     self.assertEquals(res, res_expected)


[02/50] [abbrv] ambari git commit: AMBARI-22467. YARN, MapReduce2, Hive, and Oozie Should Conditionally Install LZO (aonishuk)

Posted by ao...@apache.org.
AMBARI-22467. YARN, MapReduce2, Hive, and Oozie Should Conditionally Install LZO (aonishuk)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/20dee7f8
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/20dee7f8
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/20dee7f8

Branch: refs/heads/branch-3.0-perf
Commit: 20dee7f817d412088e1ba41a341a9fb5bbf33080
Parents: 6b17d01
Author: Andrew Onishuk <ao...@hortonworks.com>
Authored: Thu Nov 23 10:38:35 2017 +0200
Committer: Andrew Onishuk <ao...@hortonworks.com>
Committed: Thu Nov 23 10:38:35 2017 +0200

----------------------------------------------------------------------
 .../common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py        | 1 -
 .../common-services/OOZIE/4.2.0.3.0/package/scripts/oozie.py        | 1 -
 2 files changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/20dee7f8/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py
index e9d48c0..29813d3 100644
--- a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py
+++ b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie.py
@@ -193,7 +193,6 @@ def oozie(is_server=False, upgrade_type=None):
   if params.lzo_enabled:
     install_lzo_if_needed()
     Execute(format('{sudo} cp {hadoop_lib_home}/hadoop-lzo*.jar {oozie_lib_dir}'),
-      not_if  = no_op_test,
     )
   
   if is_server:

http://git-wip-us.apache.org/repos/asf/ambari/blob/20dee7f8/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/package/scripts/oozie.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/package/scripts/oozie.py b/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/package/scripts/oozie.py
index 1db16a9..96f1f1a 100644
--- a/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/package/scripts/oozie.py
+++ b/ambari-server/src/main/resources/common-services/OOZIE/4.2.0.3.0/package/scripts/oozie.py
@@ -193,7 +193,6 @@ def oozie(is_server=False):
   if params.lzo_enabled:
     install_lzo_if_needed()
     Execute(format('{sudo} cp {hadoop_lib_home}/hadoop-lzo*.jar {oozie_lib_dir}'),
-      not_if  = no_op_test,
     )
   
   if is_server:      


[08/50] [abbrv] ambari git commit: AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)

Posted by ao...@apache.org.
AMBARI-22508 Ambari 3.0: Implement new design for Admin View: User Management. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/99b19e58
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/99b19e58
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/99b19e58

Branch: refs/heads/branch-3.0-perf
Commit: 99b19e5805cf3ac291eca9c8e6a1290637b08ab6
Parents: 8e36662
Author: Andrii Tkach <at...@apache.org>
Authored: Thu Nov 23 14:02:00 2017 +0200
Committer: Andrii Tkach <at...@apache.org>
Committed: Thu Nov 23 14:02:00 2017 +0200

----------------------------------------------------------------------
 .../main/resources/ui/admin-web/app/index.html  |  17 +-
 .../resources/ui/admin-web/app/scripts/app.js   |   3 +-
 .../controllers/ClusterInformationCtrl.js       | 106 ---
 .../controllers/ambariViews/ViewsListCtrl.js    |   4 +-
 .../clusters/ClusterInformationCtrl.js          | 106 +++
 .../clusters/ClustersManageAccessCtrl.js        |  97 ---
 .../controllers/clusters/UserAccessListCtrl.js  | 351 --------
 .../controllers/groups/GroupsCreateCtrl.js      |  65 --
 .../controllers/groups/GroupsEditCtrl.js        | 180 ----
 .../controllers/groups/GroupsListCtrl.js        | 106 ---
 .../userManagement/GroupCreateCtrl.js           | 112 +++
 .../controllers/userManagement/GroupEditCtrl.js | 182 ++++
 .../userManagement/GroupsListCtrl.js            | 170 ++++
 .../userManagement/UserCreateCtrl.js            | 108 +++
 .../controllers/userManagement/UserEditCtrl.js  | 290 +++++++
 .../userManagement/UserManagementCtrl.js        |  23 +
 .../controllers/userManagement/UsersListCtrl.js | 178 ++++
 .../controllers/users/UsersCreateCtrl.js        |  75 --
 .../scripts/controllers/users/UsersListCtrl.js  | 122 ---
 .../scripts/controllers/users/UsersShowCtrl.js  | 290 -------
 .../ui/admin-web/app/scripts/i18n.config.js     |   9 +-
 .../ui/admin-web/app/scripts/routes.js          |  61 +-
 .../ui/admin-web/app/scripts/services/User.js   |   5 +-
 .../resources/ui/admin-web/app/styles/main.css  |  46 +-
 .../ui/admin-web/app/styles/user-management.css |  30 +
 .../resources/ui/admin-web/app/styles/views.css |  18 -
 .../app/views/ambariViews/viewsList.html        |  26 +-
 .../admin-web/app/views/clusterInformation.html |  87 --
 .../app/views/clusters/clusterInformation.html  |  87 ++
 .../app/views/clusters/manageAccess.html        |  63 --
 .../app/views/clusters/userAccessList.html      | 102 ---
 .../ui/admin-web/app/views/groups/create.html   |  43 -
 .../ui/admin-web/app/views/groups/edit.html     |  98 ---
 .../ui/admin-web/app/views/groups/list.html     |  80 --
 .../ui/admin-web/app/views/sideNav.html         |  22 +-
 .../app/views/userManagement/groupEdit.html     |  99 +++
 .../app/views/userManagement/groupsList.html    |  94 +++
 .../app/views/userManagement/main.html          |  36 +
 .../userManagement/modals/changePassword.html   |  46 ++
 .../userManagement/modals/groupCreate.html      |  86 ++
 .../views/userManagement/modals/userCreate.html | 147 ++++
 .../app/views/userManagement/userEdit.html      | 122 +++
 .../app/views/userManagement/usersList.html     | 119 +++
 .../ui/admin-web/app/views/users/create.html    |  82 --
 .../ui/admin-web/app/views/users/list.html      |  97 ---
 .../app/views/users/modals/changePassword.html  |  46 --
 .../ui/admin-web/app/views/users/show.html      | 122 ---
 .../clusters/UserAccessListCtrl_test.js         | 820 -------------------
 .../controllers/groups/GroupsListCtrl_test.js   | 129 ---
 .../userManagement/GroupsListCtrl_test.js       | 129 +++
 .../userManagement/UsersListCtrl_test.js        | 344 ++++++++
 .../controllers/users/UsersListCtrl_test.js     | 383 ---------
 .../test/unit/services/Utility_test.js          |  10 +-
 53 files changed, 2591 insertions(+), 3682 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/index.html
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/index.html b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
index 4a77e62..e3b817e 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/index.html
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/index.html
@@ -121,26 +121,25 @@
 <script src="scripts/app.js"></script>
 <script src="scripts/routes.js"></script>
 <script src="scripts/i18n.config.js"></script>
-<script src="scripts/controllers/ClusterInformationCtrl.js"></script>
+<script src="scripts/controllers/clusters/ClusterInformationCtrl.js"></script>
 <script src="scripts/controllers/AppCtrl.js"></script>
 <script src="scripts/controllers/SideNavCtrl.js"></script>
 <script src="scripts/controllers/authentication/AuthenticationMainCtrl.js"></script>
 <script src="scripts/controllers/loginActivities/LoginActivitiesMainCtrl.js"></script>
 <script src="scripts/controllers/loginActivities/LoginMessageMainCtrl.js"></script>
 <script src="scripts/controllers/loginActivities/HomeDirectoryCtrl.js"></script>
-<script src="scripts/controllers/users/UsersCreateCtrl.js"></script>
-<script src="scripts/controllers/users/UsersListCtrl.js"></script>
-<script src="scripts/controllers/users/UsersShowCtrl.js"></script>
-<script src="scripts/controllers/groups/GroupsListCtrl.js"></script>
-<script src="scripts/controllers/groups/GroupsCreateCtrl.js"></script>
-<script src="scripts/controllers/groups/GroupsEditCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UserManagementCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UserCreateCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UsersListCtrl.js"></script>
+<script src="scripts/controllers/userManagement/UserEditCtrl.js"></script>
+<script src="scripts/controllers/userManagement/GroupsListCtrl.js"></script>
+<script src="scripts/controllers/userManagement/GroupCreateCtrl.js"></script>
+<script src="scripts/controllers/userManagement/GroupEditCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewsListCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewsEditCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewUrlCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/ViewUrlEditCtrl.js"></script>
 <script src="scripts/controllers/ambariViews/CreateViewInstanceCtrl.js"></script>
-<script src="scripts/controllers/clusters/ClustersManageAccessCtrl.js"></script>
-<script src="scripts/controllers/clusters/UserAccessListCtrl.js"></script>
 <script src="scripts/controllers/stackVersions/StackVersionsCreateCtrl.js"></script>
 <script src="scripts/controllers/stackVersions/StackVersionsListCtrl.js"></script>
 <script src="scripts/controllers/stackVersions/StackVersionsEditCtrl.js"></script>

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
index 80e2813..225eb12 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/app.js
@@ -33,7 +33,8 @@ angular.module('ambariAdminConsole', [
   isLDAPConfigurationSupported: false,
   isLoginActivitiesSupported: false,
   maxStackTraceLength: 1000,
-  errorStorageSize: 500000
+  errorStorageSize: 500000,
+  minRowsToShowPagination: 10
 })
 .config(['RestangularProvider', '$httpProvider', '$provide', 'Settings', function(RestangularProvider, $httpProvider, $provide, Settings) {
   // Config Ajax-module

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js
deleted file mode 100644
index 059f399..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ClusterInformationCtrl.js
+++ /dev/null
@@ -1,106 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('ClusterInformationCtrl',
-['$scope', '$http', '$location', 'Cluster', '$routeParams', '$translate', '$rootScope', 'ConfirmationModal', 'Alert',
-function($scope, $http, $location, Cluster, $routeParams, $translate, $rootScope, ConfirmationModal, Alert) {
-  var $t = $translate.instant;
-  $scope.isDataLoaded = false;
-  $scope.edit = {
-    clusterName: null
-  };
-  $scope.isClusterNameEdited = false;
-
-  $scope.$watch(function() {
-    return $rootScope.cluster;
-  }, function() {
-    $scope.cluster = $rootScope.cluster;
-    if ($scope.cluster) {
-      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
-      $scope.getBlueprint();
-    }
-  }, true);
-
-  $scope.getBlueprint = function () {
-    Cluster.getBlueprint({
-      clusterName: $scope.cluster.Clusters.cluster_name
-    }).then(function (data) {
-      console.debug($t('exportBlueprint.dataLoaded'), data);
-      $scope.isDataLoaded = true;
-      var response = JSON.stringify(data, null, 4),
-        lt = /&lt;/g,
-        gt = /&gt;/g,
-        ap = /&#39;/g,
-        ic = /&#34;/g;
-      $scope.blueprint = response ? response.toString().replace(lt, "<").replace(gt, ">").replace(ap, "'").replace(ic, '"') : "";
-    });
-  };
-
-  $scope.downloadBlueprint = function () {
-    if (window.navigator.msSaveOrOpenBlob) {
-      var blob = new Blob([decodeURIComponent(encodeURI($scope.blueprint))], {
-        type: "text/csv;charset=utf-8;"
-      });
-      navigator.msSaveBlob(blob, 'blueprint.json');
-    } else {
-      var a = document.createElement('a');
-      a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI($scope.blueprint);
-      a.target = '_blank';
-      a.download = 'blueprint.json';
-      document.body.appendChild(a);
-      a.click();
-    }
-  };
-
-  $scope.toggleSaveButton = function() {
-    var value = $scope.edit.clusterName;
-    $scope.isClusterNameEdited = (value !== null && $scope.cluster.Clusters.cluster_name !== value);
-  };
-
-  $scope.confirmClusterNameChange = function() {
-    ConfirmationModal.show(
-      $t('common.clusterNameChangeConfirmation.title'),
-      $t('common.clusterNameChangeConfirmation.message', {
-        clusterName: $scope.edit.clusterName
-      })
-    )
-      .then(function () {
-        $scope.saveClusterName();
-      }).catch(function () {
-      // user clicked cancel
-      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
-      $scope.toggleSaveButton();
-    });
-  };
-
-  $scope.saveClusterName = function() {
-    var oldClusterName = $scope.cluster.Clusters.cluster_name,
-        newClusterName = $scope.edit.clusterName;
-
-    Cluster.editName(oldClusterName, newClusterName).then(function(data) {
-      $scope.cluster.Clusters.cluster_name = newClusterName;
-      $scope.edit.clusterName = newClusterName;
-      $scope.toggleSaveButton();
-      Alert.success($t('common.alerts.clusterRenamed', {clusterName: newClusterName}));
-    }).catch(function(data) {
-      Alert.error($t('common.alerts.cannotRenameCluster', {clusterName: newClusterName}), data.data.message);
-    });
-  };
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
index aa77b63..8b37dca 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/ambariViews/ViewsListCtrl.js
@@ -18,11 +18,11 @@
 'use strict';
 
 angular.module('ambariAdminConsole')
-.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$translate', function($scope, View, $modal, Alert, ConfirmationModal, $translate) {
+.controller('ViewsListCtrl',['$scope', 'View','$modal', 'Alert', 'ConfirmationModal', '$translate', 'Settings', function($scope, View, $modal, Alert, ConfirmationModal, $translate, Settings) {
   var $t = $translate.instant;
   var VIEWS_VERSION_STATUS_TIMEOUT = 5000;
   $scope.isLoading = false;
-  $scope.minInstanceForPagination = 10;
+  $scope.minInstanceForPagination = Settings.minRowsToShowPagination;
 
   function checkViewVersionStatus(view, versionObj, versionNumber) {
     var deferred = View.checkViewVersionStatus(view.view_name, versionNumber);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js
new file mode 100644
index 0000000..059f399
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClusterInformationCtrl.js
@@ -0,0 +1,106 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('ClusterInformationCtrl',
+['$scope', '$http', '$location', 'Cluster', '$routeParams', '$translate', '$rootScope', 'ConfirmationModal', 'Alert',
+function($scope, $http, $location, Cluster, $routeParams, $translate, $rootScope, ConfirmationModal, Alert) {
+  var $t = $translate.instant;
+  $scope.isDataLoaded = false;
+  $scope.edit = {
+    clusterName: null
+  };
+  $scope.isClusterNameEdited = false;
+
+  $scope.$watch(function() {
+    return $rootScope.cluster;
+  }, function() {
+    $scope.cluster = $rootScope.cluster;
+    if ($scope.cluster) {
+      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
+      $scope.getBlueprint();
+    }
+  }, true);
+
+  $scope.getBlueprint = function () {
+    Cluster.getBlueprint({
+      clusterName: $scope.cluster.Clusters.cluster_name
+    }).then(function (data) {
+      console.debug($t('exportBlueprint.dataLoaded'), data);
+      $scope.isDataLoaded = true;
+      var response = JSON.stringify(data, null, 4),
+        lt = /&lt;/g,
+        gt = /&gt;/g,
+        ap = /&#39;/g,
+        ic = /&#34;/g;
+      $scope.blueprint = response ? response.toString().replace(lt, "<").replace(gt, ">").replace(ap, "'").replace(ic, '"') : "";
+    });
+  };
+
+  $scope.downloadBlueprint = function () {
+    if (window.navigator.msSaveOrOpenBlob) {
+      var blob = new Blob([decodeURIComponent(encodeURI($scope.blueprint))], {
+        type: "text/csv;charset=utf-8;"
+      });
+      navigator.msSaveBlob(blob, 'blueprint.json');
+    } else {
+      var a = document.createElement('a');
+      a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI($scope.blueprint);
+      a.target = '_blank';
+      a.download = 'blueprint.json';
+      document.body.appendChild(a);
+      a.click();
+    }
+  };
+
+  $scope.toggleSaveButton = function() {
+    var value = $scope.edit.clusterName;
+    $scope.isClusterNameEdited = (value !== null && $scope.cluster.Clusters.cluster_name !== value);
+  };
+
+  $scope.confirmClusterNameChange = function() {
+    ConfirmationModal.show(
+      $t('common.clusterNameChangeConfirmation.title'),
+      $t('common.clusterNameChangeConfirmation.message', {
+        clusterName: $scope.edit.clusterName
+      })
+    )
+      .then(function () {
+        $scope.saveClusterName();
+      }).catch(function () {
+      // user clicked cancel
+      $scope.edit.clusterName = $scope.cluster.Clusters.cluster_name;
+      $scope.toggleSaveButton();
+    });
+  };
+
+  $scope.saveClusterName = function() {
+    var oldClusterName = $scope.cluster.Clusters.cluster_name,
+        newClusterName = $scope.edit.clusterName;
+
+    Cluster.editName(oldClusterName, newClusterName).then(function(data) {
+      $scope.cluster.Clusters.cluster_name = newClusterName;
+      $scope.edit.clusterName = newClusterName;
+      $scope.toggleSaveButton();
+      Alert.success($t('common.alerts.clusterRenamed', {clusterName: newClusterName}));
+    }).catch(function(data) {
+      Alert.error($t('common.alerts.cannotRenameCluster', {clusterName: newClusterName}), data.data.message);
+    });
+  };
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
deleted file mode 100644
index 3a9ad67..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/ClustersManageAccessCtrl.js
+++ /dev/null
@@ -1,97 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('ClustersManageAccessCtrl', ['$scope', '$location', 'Cluster', '$routeParams', 'Alert', 'PermissionLoader', 'PermissionSaver', '$translate', 'RoleDetailsModal', '$timeout', function($scope, $location, Cluster, $routeParams, Alert, PermissionLoader, PermissionSaver, $translate, RoleDetailsModal, $timeout) {
-  var $t = $translate.instant;
-  $scope.getConstant = function (key) {
-    return $t(key).toLowerCase();
-  };
-  $scope.identity = angular.identity;
-  function reloadClusterData(){
-    PermissionLoader.getClusterPermissions({
-      clusterId: $routeParams.id
-    }).then(function(permissions) {
-      // Refresh data for rendering
-      $scope.permissionsEdit = permissions;
-      $scope.permissions = angular.copy(permissions);
-      //"$scope.isDataLoaded" should be set to true on initial load after "$scope.permissionsEdit" watcher
-      $timeout(function() {
-        $scope.isDataLoaded = true;
-      });
-      var orderedRoles = Cluster.orderedRoles;
-      var pms = [];
-      for (var key=0;key<orderedRoles.length;key++) {
-        pms.push($scope.permissions[orderedRoles[key]]);
-      }
-      $scope.permissions = pms;
-    })
-    .catch(function(data) {
-      Alert.error($t('clusters.alerts.cannotLoadClusterData'), data.data.message);
-    });
-  }
-
-  $scope.isDataLoaded = false;
-  reloadClusterData();
-  $scope.isEditMode = false;
-  $scope.permissions = {};
-  $scope.clusterName = $routeParams.id;
-
-
-  $scope.toggleEditMode = function() {
-    $scope.isEditMode = !$scope.isEditMode;
-  };
-
-  $scope.cancel = function() {
-    $scope.isEditMode = false;
-    $scope.permissionsEdit = angular.copy($scope.permissions); // Reset textedit areaes
-  };
-
-  $scope.save = function() {
-    PermissionSaver.saveClusterPermissions(
-      $scope.permissionsEdit,
-      {
-        clusterId: $routeParams.id
-      }
-    ).then(reloadClusterData)
-    .catch(function(data) {
-      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
-      reloadClusterData();
-    });
-    $scope.isEditMode = false;
-  };
-
-  $scope.$watch(function() {
-    return $scope.permissionsEdit;
-  }, function(newValue) {
-    if (newValue && $scope.isDataLoaded) {
-      $scope.save();
-    }
-  }, true);
-
-  $scope.switchToList = function() {
-    $location.url('/clusters/' + $routeParams.id + '/userAccessList');
-  };
-
-  $scope.showHelpPage = function() {
-    Cluster.getRolesWithAuthorizations().then(function(roles) {
-      RoleDetailsModal.show(roles);
-    });
-  };
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
deleted file mode 100644
index 9e83b91..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/clusters/UserAccessListCtrl.js
+++ /dev/null
@@ -1,351 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('UserAccessListCtrl',['$scope', '$location', 'Cluster', '$modal', '$rootScope', '$routeParams', 'PermissionSaver', 'Alert', '$translate', 'RoleDetailsModal',
-function($scope, $location, Cluster, $modal, $rootScope, $routeParams, PermissionSaver, Alert, $translate, RoleDetailsModal) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    users: $t('common.users').toLowerCase(),
-    groups: $t('common.groups').toLowerCase()
-  };
-  $scope.users = [];
-  $scope.usersPerPage = 10;
-  $scope.currentPage = 1;
-  $scope.totalUsers = 1;
-  $scope.currentNameFilter = '';
-  $scope.maxVisiblePages = 20;
-  $scope.roles = [];
-  $scope.clusterId = $routeParams.id;
-  $scope.tableInfo = {
-    total: 0,
-    showed: 0,
-    filtered: 0
-  };
-  $scope.isNotEmptyFilter = true;
-  $scope.NONE_ROLE = {
-    "permission_label" : $t('common.none'),
-    "permission_name" : "CLUSTER.NONE"
-  };
-  $scope.ALL_ROLE = {
-    "permission_label" : $t('common.all'),
-    "permission_name" : ""
-  };
-  $scope.AMBARI_ADMIN_ROLE = {
-    "permission_label" : $t('users.roles.ambariAdmin'),
-    "permission_name" : "AMBARI.ADMINISTRATOR"
-  };
-
-  $scope.pageChanged = function() {
-    $scope.loadUsers();
-  };
-  $scope.usersPerPageChanges = function() {
-    $scope.resetPagination();
-  };
-
-  $scope.loadUsers = function(){
-    Cluster.getPrivilegesWithFilters({
-      nameFilter: $scope.currentNameFilter,
-      typeFilter: $scope.currentTypeFilter,
-      roleFilter: $scope.currentRoleFilter,
-      currentPage: $scope.currentPage,
-      usersPerPage: $scope.usersPerPage
-    }).then(function(data) {
-      $scope.totalUsers = data.itemTotal;
-      $scope.users = data.items.map(function (user) {
-        var privilege = $scope.pickEffectivePrivilege(user.privileges);
-        // Redefine principal_name and principal type in case of None
-        privilege.principal_name = user.Users? user.Users.user_name : user.Groups.group_name;
-        if (privilege.permission_label === $t('users.roles.none')) {
-          privilege.principal_type = user.Users ? 'USER' : 'GROUP';
-        }
-        var name = encodeURIComponent(privilege.principal_name);
-        privilege.encoded_name = name;
-        privilege.original_perm = privilege.permission_name;
-        privilege.url = user.Users? ('users/' + name) : ('groups/' + name + '/edit');
-        privilege.editable = Cluster.ineditableRoles.indexOf(privilege.permission_name) == -1;
-        return privilege;
-      });
-      $scope.tableInfo.total = data.itemTotal;
-      $scope.tableInfo.showed = data.items.length;
-    });
-  };
-
-  $scope.pickEffectivePrivilege = function(privileges) {
-    if (privileges && privileges.length > 1) {
-      return privileges.reduce(function(prev, cur) {
-        var prevIndex = $scope.getRoleRank(prev.PrivilegeInfo.permission_name);
-        var curIndex = $scope.getRoleRank(cur.PrivilegeInfo.permission_name)
-        return (prevIndex < curIndex) ? prev : cur;
-      }).PrivilegeInfo;
-    } else if (privileges && privileges.length == 1 && privileges[0].PrivilegeInfo.permission_name !== "VIEW.USER") {
-      return privileges[0].PrivilegeInfo;
-    } else {
-      return angular.copy($scope.NONE_ROLE);
-    }
-  };
-
-  $scope.loadRoles = function() {
-    Cluster.getPermissions().then(function(data) {
-      $scope.roles = data.map(function(item) {
-        return item.PermissionInfo;
-      });
-      // [All, Administrator, ...roles..., None]
-      $scope.roles.unshift(angular.copy($scope.AMBARI_ADMIN_ROLE));
-      $scope.roles.unshift(angular.copy($scope.ALL_ROLE));
-      $scope.roles.push(angular.copy($scope.NONE_ROLE));
-
-      // create filter select list
-      $scope.roleFilterOptions = angular.copy($scope.roles);
-      $scope.roleFilterOptions.pop();  // filter does not support None
-      $scope.roleFilterOptions = $scope.roleFilterOptions.map(function(o) {
-        return {label: o.permission_label, value: o.permission_name};
-      });
-      $scope.currentRoleFilter = $scope.roleFilterOptions[0];
-
-      // create value select list
-      $scope.roleValueOptions = angular.copy($scope.roles)
-      $scope.roleValueOptions.shift(); // value change does not support all/administrator
-      $scope.roleValueOptions.shift();
-    });
-  };
-
-  $scope.getRoleRank = function(permission_name) {
-    var orderedRoles = Cluster.orderedRoles.concat(['VIEW.USER','CLUSTER.NONE']);
-    var index = orderedRoles.indexOf(permission_name);
-    return index;
-  };
-
-  $scope.save = function(user) {
-    var fromNone = (user.original_perm === $scope.NONE_ROLE.permission_name);
-    if (fromNone) {
-      $scope.addPrivilege(user);
-      return;
-    }
-
-    if ($scope.isUserActive) {
-      Cluster.getPrivilegesForResource({
-          nameFilter : user.user_name,
-          typeFilter : $scope.currentTypeFilter
-      }).then(function(data) {
-        var arrayOfPrivileges = data.items[0].privileges;
-        var privilegesOfTypeUser = [];
-        var privilegesOfTypeGroup = [];
-        for (var i = 0; i < arrayOfPrivileges.length; i++) {
-          if(arrayOfPrivileges[i].PrivilegeInfo.permission_name != "VIEW.USER") {
-            if(arrayOfPrivileges[i].PrivilegeInfo.principal_type === "GROUP"){
-              privilegesOfTypeGroup.push(arrayOfPrivileges[i]);
-            } else {
-              privilegesOfTypeUser.push(arrayOfPrivileges[i].PrivilegeInfo);
-            }
-          }
-        }
-
-        var effectivePrivilege = $scope.pickEffectivePrivilege(arrayOfPrivileges);
-        var effectivePrivilegeFromGroups = $scope.pickEffectivePrivilege(privilegesOfTypeGroup);
-        user.principal_type = 'USER';
-        user.original_perm = effectivePrivilege.permission_name;
-        user.editable = (Cluster.ineditableRoles.indexOf(effectivePrivilege.permission_name) === -1);
-
-        var userIndex = $scope.getRoleRank(user.permission_name);
-        var groupIndex = $scope.getRoleRank(effectivePrivilegeFromGroups.permission_name);
-
-        // Process when it's NONE privilege or higher than current effective group privilege
-        if (userIndex <= groupIndex || user.permission_name == $scope.NONE_ROLE.permission_name) {
-          var privilege_ids = privilegesOfTypeUser.filter(function(privilegeOfTypeUser) {
-            return privilegeOfTypeUser.principal_type !== 'ROLE';
-          }).map(function (privilegeOfTypeUser) {
-            return privilegeOfTypeUser.privilege_id;
-          });
-
-          // Purge existing user level privileges if there is any
-          if(privilege_ids.length !== 0) {
-            Cluster.deleteMultiplePrivileges(
-                $routeParams.id,
-                privilege_ids
-            )
-            .then(function() {
-              $scope.addPrivilege(user);
-            });
-          } else {
-            $scope.addPrivilege(user);
-          }
-        } else {
-          Alert.error($t('common.alerts.cannotSavePermissions'),
-              $t('users.alerts.usersEffectivePrivilege', {user_name : user.user_name})
-          );
-          $scope.loadUsers();
-        }
-      });
-    } else {
-      Cluster.getPrivilegesForResource({
-          nameFilter : user.group_name,
-          typeFilter : $scope.currentTypeFilter
-      }).then(function(data) {
-        var arrayOfPrivileges = data.items[0].privileges;
-        var privilegesOfTypeGroup = [];
-        var privilege = $scope.pickEffectivePrivilege(arrayOfPrivileges);
-        user.principal_type = 'GROUP';
-        user.original_perm = privilege.permission_name;
-        user.editable = (Cluster.ineditableRoles.indexOf(privilege.permission_name) === -1);
-
-        arrayOfPrivileges.forEach(function(privilegeOfTypeGroup) {
-          if(privilegeOfTypeGroup.PrivilegeInfo.permission_name != "VIEW.USER") {
-            if (privilegeOfTypeGroup.PrivilegeInfo.principal_type === "GROUP") {
-              privilegesOfTypeGroup.push(privilegeOfTypeGroup.PrivilegeInfo);
-            }
-          }
-        });
-
-        var privilege_ids = [];
-        privilegesOfTypeGroup.forEach(function(privilegeOfTypeGroup) {
-          privilege_ids.push(privilegeOfTypeGroup.privilege_id);
-        });
-
-        //delete all privileges of type GROUP, if they exist
-        //then add the privilege for the group, after which the group displays the effective privilege
-        if(privilege_ids.length !== 0) {
-          Cluster.deleteMultiplePrivileges(
-              $routeParams.id,
-              privilege_ids
-          )
-          .then(function() {
-            $scope.addPrivilege(user);
-          });
-        } else {
-          $scope.addPrivilege(user);
-        }
-      });
-    }
-  };
-
-  $scope.cancel = function(user) {
-    user.permission_name = user.original_perm;
-  };
-
-  $scope.addPrivilege = function(user) {
-    var changeToNone = user.permission_name == $scope.NONE_ROLE.permission_name;
-    if (changeToNone) {
-      if ($scope.isUserActive) {
-        Alert.success($t('users.alerts.roleChangedToNone', {
-            user_name : user.user_name
-        }));
-      } else {
-        $scope.showSuccess(user);
-      }
-      $scope.loadUsers();
-      return;
-    }
-    Cluster.createPrivileges(
-      {
-        clusterId: $routeParams.id
-      },
-      [{PrivilegeInfo: {
-        permission_name: user.permission_name,
-        principal_name: user.principal_name,
-        principal_type: user.principal_type
-      }}]
-    ).then(function() {
-        $scope.showSuccess(user);
-        $scope.loadUsers();
-      })
-      .catch(function(data) {
-        Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
-        $scope.loadUsers();
-      });
-  };
-
-  $scope.showSuccess = function(user) {
-    Alert.success($t('users.alerts.roleChanged', {
-      name: user.principal_name,
-      role: $scope.roles.filter(function(r){
-          return r.permission_name == user.permission_name}
-      )[0].permission_label
-    }));
-  };
-
-  $scope.resetPagination = function() {
-    $scope.currentPage = 1;
-    $scope.loadUsers();
-  };
-  $scope.currentRoleFilter = { label:$t('common.all'), value: '' };
-
-
-  $scope.typeFilterOptions = [
-    {label: $t('common.user'), value: 'USER'},
-    {label: $t('common.group'), value: 'GROUP'}
-  ];
-
-  $scope.isUserActive = true;
-
-  $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
-  $scope.switchToUser = function() {
-    if (!$scope.isUserActive) {
-      $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-      $scope.isUserActive = true;
-      $scope.resetPagination();
-    }
-  };
-
-  $scope.switchToGroup = function() {
-    if ($scope.isUserActive) {
-      $scope.currentTypeFilter = $scope.typeFilterOptions[1];
-      $scope.isUserActive = false;
-      $scope.resetPagination();
-    }
-  };
-
-  $scope.clearFilters = function() {
-    $scope.currentNameFilter = '';
-    $scope.currentRoleFilter = $scope.roleFilterOptions[0];
-    $scope.resetPagination();
-  };
-
-  $scope.loadRoles();
-  $scope.loadUsers();
-
-  $scope.$watch(
-    function (scope) {
-      return Boolean(scope.currentNameFilter || (scope.currentRoleFilter && scope.currentRoleFilter.value));
-    },
-    function (newValue, oldValue, scope) {
-      scope.isNotEmptyFilter = newValue;
-    }
-  );
-
-  $rootScope.$watch(function(scope) {
-    return scope.LDAPSynced;
-  }, function(LDAPSynced) {
-    if(LDAPSynced === true){
-      $rootScope.LDAPSynced = false;
-      $scope.loadUsers();
-    }
-  });
-
-  $scope.switchToBlock = function() {
-    $location.url('/clusters/' + $routeParams.id + '/manageAccess');
-  };
-
-  $scope.showHelpPage = function() {
-    Cluster.getRolesWithAuthorizations().then(function(roles) {
-      RoleDetailsModal.show(roles);
-    });
-  };
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
deleted file mode 100644
index 67743a0..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsCreateCtrl.js
+++ /dev/null
@@ -1,65 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('GroupsCreateCtrl',['$scope', 'Group', '$location', 'Alert', 'UnsavedDialog', '$translate', function($scope, Group, $location, Alert, UnsavedDialog, $translate) {
-  var $t = $translate.instant;
-  $scope.group = new Group();
-  var targetUrl = '/groups';
-
-  $scope.createGroup = function() {
-    $scope.form.submitted = true;
-    if ($scope.form.$valid){
-      $scope.group.save().then(function() {
-        Alert.success($t('groups.alerts.groupCreated', {groupName: $scope.group.group_name}));
-        $scope.form.$setPristine();
-        $location.path(targetUrl);
-      })
-      .catch(function(data) {
-        Alert.error($t('groups.alerts.groupCreationError'), data.data.message);
-      });
-    }
-  };
-
-  $scope.cancel = function() {
-    $scope.form.$setPristine();
-    $location.path('/groups');
-  };
-
-  $scope.$on('$locationChangeStart', function(event, __targetUrl) {
-    if( $scope.form.$dirty ){
-      UnsavedDialog().then(function(action) {
-        targetUrl = __targetUrl.split('#').pop();
-        switch(action){
-          case 'save':
-            $scope.createGroup();
-            break;
-          case 'discard':
-            $scope.form.$setPristine();
-            $location.path(targetUrl);
-            break;
-          case 'cancel':
-            targetUrl = '/groups';
-            break;
-        }
-      });
-      event.preventDefault();
-    }
-  });
-}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
deleted file mode 100644
index a63ebe2..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsEditCtrl.js
+++ /dev/null
@@ -1,180 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('GroupsEditCtrl',['$scope', 'Group', '$routeParams', 'Cluster', 'View', 'Alert', 'ConfirmationModal', '$location', 'GroupConstants', '$translate', function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $location, GroupConstants, $translate) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    group: $t('common.group'),
-    view: $t('common.view').toLowerCase(),
-    cluster: $t('common.cluster').toLowerCase()
-  };
-  $scope.editMode = false;
-  $scope.group = new Group($routeParams.id);
-  $scope.group.editingUsers = [];
-  $scope.groupMembers = [];
-  $scope.dataLoaded = false;
-  
-  $scope.isMembersEditing = false;
-
-  $scope.$watch(function() {
-    return $scope.group.editingUsers;
-  }, function(newValue) {
-    if(newValue && !angular.equals(newValue, $scope.groupMembers)){
-      $scope.updateMembers();  
-    }
-  }, true);
-  
-  $scope.enableMembersEditing = function() {
-    $scope.isMembersEditing = true;
-    $scope.group.editingUsers = angular.copy($scope.groupMembers);
-  };
-  $scope.cancelUpdate = function() {
-    $scope.isMembersEditing = false;
-    $scope.group.editingUsers = '';
-  };
-  $scope.updateMembers = function() {
-    var newMembers = $scope.group.editingUsers.toString().split(',').filter(function(item) {
-      return item.trim();}
-    ).map(function(item) {
-        return item.trim()
-      }
-    );
-    $scope.group.members = newMembers;
-    $scope.group.saveMembers().catch(function(data) {
-        Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
-      }).finally(function() {
-        loadMembers();
-      });
-    $scope.isMembersEditing = false;
-  };
-
-
-  function loadMembers(){
-    $scope.group.getMembers().then(function(members) {
-      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
-      $scope.groupMembers = members;
-      $scope.group.editingUsers = angular.copy($scope.groupMembers);
-    });
-  }    
-  
-  $scope.group.isLDAP().then(function(isLDAP) {
-    $scope.group.ldap_group = isLDAP;
-    $scope.group.getGroupType().then(function() {
-      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
-    });
-    loadMembers();
-  });
-
-  $scope.group.getGroupType();
-
-  $scope.deleteGroup = function(group) {
-    ConfirmationModal.show(
-      $t('common.delete', {
-        term: $t('common.group')
-      }),
-      $t('common.deleteConfirmation', {
-        instanceType: $t('common.group').toLowerCase(),
-        instanceName: '"' + group.group_name + '"'
-      })
-    ).then(function() {
-      Cluster.getPrivilegesForResource({
-        nameFilter : group.group_name,
-        typeFilter : {value: 'GROUP'}
-      }).then(function(data) {
-        var clusterPrivilegesIds = [];
-        var viewsPrivileges = [];
-        if (data.items && data.items.length) {
-          angular.forEach(data.items[0].privileges, function(privilege) {
-            if (privilege.PrivilegeInfo.principal_type === 'GROUP') {
-              if (privilege.PrivilegeInfo.type === 'VIEW') {
-                viewsPrivileges.push({
-                  id: privilege.PrivilegeInfo.privilege_id,
-                  view_name: privilege.PrivilegeInfo.view_name,
-                  version: privilege.PrivilegeInfo.version,
-                  instance_name: privilege.PrivilegeInfo.instance_name
-                });
-              } else {
-                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
-              }
-            }
-          });
-        }
-        group.destroy().then(function() {
-          $location.path('/groups');
-          if (clusterPrivilegesIds.length) {
-            Cluster.getAllClusters().then(function (clusters) {
-              var clusterName = clusters[0].Clusters.cluster_name;
-              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
-            });
-          }
-          angular.forEach(viewsPrivileges, function(privilege) {
-            View.deletePrivilege(privilege);
-          });
-        });
-      });
-    });
-  };
-
-
-  $scope.removePrivilege = function(name, privilege) {
-    var privilegeObject = {
-        id: privilege.privilege_id,
-        view_name: privilege.view_name,
-        version: privilege.version,
-        instance_name: name
-    };
-    View.deletePrivilege(privilegeObject).then(function() {
-      loadPrivileges();
-    });
-  };
-
-function loadPrivileges() {
-  // Load privileges
-  Group.getPrivileges($routeParams.id).then(function(data) {
-    var privileges = {
-      clusters: {},
-      views: {}
-    };
-    angular.forEach(data.data.items, function(privilege) {
-      privilege = privilege.PrivilegeInfo;
-      if(privilege.type === 'CLUSTER'){
-        // This is cluster
-        privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || [];
-        privileges.clusters[privilege.cluster_name].push(privilege.permission_label);
-      } else if ( privilege.type === 'VIEW'){
-        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
-        privileges.views[privilege.instance_name].version = privilege.version;
-        privileges.views[privilege.instance_name].view_name = privilege.view_name;
-        privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
-        privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
-      }
-    });
-
-    $scope.privileges = data.data.items.length ? privileges : null;
-    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
-    $scope.noViewPriv = $.isEmptyObject(privileges.views);
-    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
-    $scope.dataLoaded = true;
-  }).catch(function(data) {
-    Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
-  });
-}
-loadPrivileges();
-}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
deleted file mode 100644
index 7cc590e..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/groups/GroupsListCtrl.js
+++ /dev/null
@@ -1,106 +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.
- */
-'use strict';
-
-angular.module('ambariAdminConsole')
-.controller('GroupsListCtrl',['$scope', 'Group', '$modal', 'ConfirmationModal', '$rootScope', 'GroupConstants', '$translate', function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $translate) {
-  var $t = $translate.instant;
-  $scope.constants = {
-    groups: $t('common.groups').toLowerCase()
-  };
-  $scope.isLoading = false;
-  $scope.groups = [];
-
-  $scope.groupsPerPage = 10;
-  $scope.currentPage = 1;
-  $scope.totalGroups = 1;
-  $scope.currentNameFilter = '';
-  $scope.maxVisiblePages=20;
-  $scope.tableInfo = {
-    total: 0,
-    showed: 0
-  };
-  $scope.isNotEmptyFilter = true;
-
-  $scope.pageChanged = function() {
-    loadGroups();
-  };
-  $scope.groupsPerPageChanges = function() {
-    loadGroups();
-  };
-
-  $scope.resetPagination = function() {
-    $scope.currentPage = 1;
-    loadGroups();
-  };
-
-  function loadGroups(){
-    $scope.isLoading = true;
-    Group.all({
-      currentPage: $scope.currentPage, 
-      groupsPerPage: $scope.groupsPerPage, 
-      searchString: $scope.currentNameFilter,
-      group_type: $scope.currentTypeFilter.value
-    }).then(function(groups) {
-      $scope.isLoading = false;
-      $scope.totalGroups = groups.itemTotal;
-      $scope.groups = groups.map(Group.makeGroup);
-      $scope.tableInfo.total = groups.itemTotal;
-      $scope.tableInfo.showed = groups.length;
-    })
-    .catch(function(data) {
-      console.error($t('groups.alerts.getGroupsListError'));
-    });
-  }
-
-  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
-    .concat(Object.keys(GroupConstants.TYPES).map(function(key) {
-      return {
-        label: $t(GroupConstants.TYPES[key].LABEL_KEY),
-        value: GroupConstants.TYPES[key].VALUE
-      };
-  }));
-  $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-
-  $scope.clearFilters = function () {
-    $scope.currentNameFilter = '';
-    $scope.currentTypeFilter = $scope.typeFilterOptions[0];
-    $scope.resetPagination();
-  };
-  
-  loadGroups();
-
-  $scope.$watch(
-    function (scope) {
-      return Boolean(scope.currentNameFilter || (scope.currentTypeFilter && scope.currentTypeFilter.value !== '*'));
-    },
-    function (newValue, oldValue, scope) {
-      scope.isNotEmptyFilter = newValue;
-    }
-  );
-
-  $rootScope.$watch(function(scope) {
-    return scope.LDAPSynced;
-  }, function(LDAPSynced) {
-    if(LDAPSynced === true){
-      $rootScope.LDAPSynced = false;
-      loadGroups();
-    }
-  });
-
-}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
new file mode 100644
index 0000000..94a2c9f
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupCreateCtrl.js
@@ -0,0 +1,112 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('GroupCreateCtrl',
+['$scope', '$rootScope', 'Group', '$location', 'Alert', 'UnsavedDialog', '$translate', '$modalInstance', 'Cluster',
+function($scope, $rootScope, Group, $location, Alert, UnsavedDialog, $translate, $modalInstance, Cluster) {
+  var $t = $translate.instant;
+
+  $scope.form = {};
+  $scope.formData = {
+    groupName: '',
+    members: [],
+    role: ''
+  };
+  $scope.roleOptions = [];
+
+
+  function loadRoles() {
+    Cluster.getPermissions().then(function(data) {
+      $scope.roleOptions = data.map(function(item) {
+        return item.PermissionInfo;
+      });
+    });
+  }
+
+  function unsavedChangesCheck() {
+    if ($scope.form.groupCreateForm.$dirty) {
+      UnsavedDialog().then(function (action) {
+        switch (action) {
+          case 'save':
+            $scope.save();
+            break;
+          case 'discard':
+            $modalInstance.close('discard');
+            break;
+          case 'cancel':
+            break;
+        }
+      });
+    } else {
+      $modalInstance.close('discard');
+    }
+  }
+
+  function saveMembers(group, members) {
+    group.members = members.filter(function(item) {
+      return item.trim();
+    }).map(function(item) {
+      return item.trim();
+    });
+    group.saveMembers().catch(function(data) {
+      Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
+    });
+  }
+
+  $scope.save = function () {
+    $scope.form.groupCreateForm.submitted = true;
+    if ($scope.form.groupCreateForm.$valid) {
+      var group = new Group($scope.formData.groupName);
+      group.save().then(function () {
+        saveMembers(group, $scope.formData.members);
+        saveRole();
+        $modalInstance.dismiss('created');
+        Alert.success($t('groups.alerts.groupCreated', {groupName: $scope.formData.groupName}));
+      })
+      .catch(function (data) {
+        Alert.error($t('groups.alerts.groupCreationError'), data.data.message);
+      });
+    }
+  };
+
+  function saveRole() {
+    Cluster.createPrivileges(
+      {
+        clusterId: $rootScope.cluster.Clusters.cluster_name
+      },
+      [{PrivilegeInfo: {
+        permission_name: $scope.roleOptions.filter(function(role) {
+          return role.permission_id == Number($scope.formData.role);
+        })[0].permission_name,
+        principal_name: $scope.formData.groupName,
+        principal_type: 'GROUP'
+      }}]
+    )
+      .catch(function(data) {
+        Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+      });
+  }
+
+  $scope.cancel = function () {
+    unsavedChangesCheck();
+  };
+
+  loadRoles();
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
new file mode 100644
index 0000000..ff705eb
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupEditCtrl.js
@@ -0,0 +1,182 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('GroupEditCtrl',
+['$scope', 'Group', '$routeParams', 'Cluster', 'View', 'Alert', 'ConfirmationModal', '$location', 'GroupConstants', '$translate',
+function($scope, Group, $routeParams, Cluster, View, Alert, ConfirmationModal, $location, GroupConstants, $translate) {
+  var $t = $translate.instant;
+  $scope.constants = {
+    group: $t('common.group'),
+    view: $t('common.view').toLowerCase(),
+    cluster: $t('common.cluster').toLowerCase()
+  };
+  $scope.editMode = false;
+  $scope.group = new Group($routeParams.id);
+  $scope.group.editingUsers = [];
+  $scope.groupMembers = [];
+  $scope.dataLoaded = false;
+  
+  $scope.isMembersEditing = false;
+
+  $scope.$watch(function() {
+    return $scope.group.editingUsers;
+  }, function(newValue) {
+    if(newValue && !angular.equals(newValue, $scope.groupMembers)){
+      $scope.updateMembers();  
+    }
+  }, true);
+  
+  $scope.enableMembersEditing = function() {
+    $scope.isMembersEditing = true;
+    $scope.group.editingUsers = angular.copy($scope.groupMembers);
+  };
+  $scope.cancelUpdate = function() {
+    $scope.isMembersEditing = false;
+    $scope.group.editingUsers = '';
+  };
+  $scope.updateMembers = function() {
+    var newMembers = $scope.group.editingUsers.toString().split(',').filter(function(item) {
+      return item.trim();}
+    ).map(function(item) {
+        return item.trim()
+      }
+    );
+    $scope.group.members = newMembers;
+    $scope.group.saveMembers().catch(function(data) {
+        Alert.error($t('groups.alerts.cannotUpdateGroupMembers'), "<div class='break-word'>" + data.message + "</div>");
+      }).finally(function() {
+        loadMembers();
+      });
+    $scope.isMembersEditing = false;
+  };
+
+
+  function loadMembers(){
+    $scope.group.getMembers().then(function(members) {
+      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
+      $scope.groupMembers = members;
+      $scope.group.editingUsers = angular.copy($scope.groupMembers);
+    });
+  }    
+  
+  $scope.group.isLDAP().then(function(isLDAP) {
+    $scope.group.ldap_group = isLDAP;
+    $scope.group.getGroupType().then(function() {
+      $scope.group.groupTypeName = $t(GroupConstants.TYPES[$scope.group.group_type].LABEL_KEY);
+    });
+    loadMembers();
+  });
+
+  $scope.group.getGroupType();
+
+  $scope.deleteGroup = function(group) {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.group')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.group').toLowerCase(),
+        instanceName: '"' + group.group_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : group.group_name,
+        typeFilter : {value: 'GROUP'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'GROUP') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        group.destroy().then(function() {
+          $location.path('/userManagement');
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+        });
+      });
+    });
+  };
+
+
+  $scope.removePrivilege = function(name, privilege) {
+    var privilegeObject = {
+        id: privilege.privilege_id,
+        view_name: privilege.view_name,
+        version: privilege.version,
+        instance_name: name
+    };
+    View.deletePrivilege(privilegeObject).then(function() {
+      loadPrivileges();
+    });
+  };
+
+function loadPrivileges() {
+  // Load privileges
+  Group.getPrivileges($routeParams.id).then(function(data) {
+    var privileges = {
+      clusters: {},
+      views: {}
+    };
+    angular.forEach(data.data.items, function(privilege) {
+      privilege = privilege.PrivilegeInfo;
+      if(privilege.type === 'CLUSTER'){
+        // This is cluster
+        privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || [];
+        privileges.clusters[privilege.cluster_name].push(privilege.permission_label);
+      } else if ( privilege.type === 'VIEW'){
+        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
+        privileges.views[privilege.instance_name].version = privilege.version;
+        privileges.views[privilege.instance_name].view_name = privilege.view_name;
+        privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
+        privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+      }
+    });
+
+    $scope.privileges = data.data.items.length ? privileges : null;
+    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
+    $scope.noViewPriv = $.isEmptyObject(privileges.views);
+    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
+    $scope.dataLoaded = true;
+  }).catch(function(data) {
+    Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
+  });
+}
+loadPrivileges();
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
new file mode 100644
index 0000000..af77ba9
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/GroupsListCtrl.js
@@ -0,0 +1,170 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('GroupsListCtrl',
+['$scope', 'Group', '$modal', 'ConfirmationModal', '$rootScope', 'GroupConstants', '$translate', 'Settings', 'Cluster', 'View', '$location',
+function($scope, Group, $modal, ConfirmationModal, $rootScope, GroupConstants, $translate, Settings, Cluster, View, $location) {
+  var $t = $translate.instant;
+  $scope.constants = {
+    groups: $t('common.groups').toLowerCase()
+  };
+  $scope.minRowsToShowPagination = Settings.minRowsToShowPagination;
+  $scope.isLoading = false;
+  $scope.groups = [];
+
+  $scope.groupsPerPage = 10;
+  $scope.currentPage = 1;
+  $scope.totalGroups = 0;
+  $scope.filter = {
+    name: '',
+    type: null
+  };
+  $scope.maxVisiblePages=20;
+  $scope.tableInfo = {
+    total: 0,
+    showed: 0
+  };
+  $scope.isNotEmptyFilter = true;
+
+  $scope.pageChanged = function() {
+    loadGroups();
+  };
+  $scope.groupsPerPageChanges = function() {
+    loadGroups();
+  };
+
+  $scope.resetPagination = function() {
+    $scope.currentPage = 1;
+    loadGroups();
+  };
+
+  function loadGroups(){
+    $scope.isLoading = true;
+    Group.all({
+      currentPage: $scope.currentPage, 
+      groupsPerPage: $scope.groupsPerPage, 
+      searchString: $scope.filter.name,
+      group_type: $scope.filter.type.value
+    }).then(function(groups) {
+      $scope.isLoading = false;
+      $scope.totalGroups = groups.itemTotal;
+      $scope.groups = groups.map(Group.makeGroup);
+      $scope.tableInfo.total = groups.itemTotal;
+      $scope.tableInfo.showed = groups.length;
+    })
+    .catch(function(data) {
+      console.error($t('groups.alerts.getGroupsListError'));
+    });
+  }
+
+  $scope.typeFilterOptions = [{ label: $t('common.all'), value: '*'}]
+    .concat(Object.keys(GroupConstants.TYPES).map(function(key) {
+      return {
+        label: $t(GroupConstants.TYPES[key].LABEL_KEY),
+        value: GroupConstants.TYPES[key].VALUE
+      };
+  }));
+  $scope.filter.type = $scope.typeFilterOptions[0];
+
+  $scope.clearFilters = function () {
+    $scope.filter.name = '';
+    $scope.filter.type = $scope.typeFilterOptions[0];
+    $scope.resetPagination();
+  };
+  
+  loadGroups();
+
+  $scope.$watch(
+    function (scope) {
+      return Boolean(scope.filter.name || (scope.filter.type && scope.filter.type.value !== '*'));
+    },
+    function (newValue, oldValue, scope) {
+      scope.isNotEmptyFilter = newValue;
+    }
+  );
+
+  $rootScope.$watch(function(scope) {
+    return scope.LDAPSynced;
+  }, function(LDAPSynced) {
+    if(LDAPSynced === true){
+      $rootScope.LDAPSynced = false;
+      loadGroups();
+    }
+  });
+
+  $scope.createGroup = function () {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/userManagement/modals/groupCreate.html',
+      controller: 'GroupCreateCtrl',
+      backdrop: 'static'
+    });
+
+    modalInstance.result.catch(loadGroups);
+  };
+
+  $scope.deleteGroup = function(group) {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.group')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.group').toLowerCase(),
+        instanceName: '"' + group.group_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : group.group_name,
+        typeFilter : {value: 'GROUP'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'GROUP') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        group.destroy().then(function() {
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+          loadGroups();
+        });
+      });
+    });
+  };
+
+}]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
new file mode 100644
index 0000000..34637ae
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserCreateCtrl.js
@@ -0,0 +1,108 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('UserCreateCtrl',
+['$scope', '$rootScope', 'User', '$location', 'Alert', 'UnsavedDialog', '$translate', 'Cluster', '$modalInstance',
+function($scope, $rootScope, User, $location, Alert, UnsavedDialog, $translate, Cluster, $modalInstance) {
+  var $t = $translate.instant;
+
+  $scope.form = {};
+  $scope.formData = {
+    userName: '',
+    password: '',
+    confirmPassword: '',
+    role: null,
+    isAdmin: false,
+    isActive: true
+  };
+  $scope.roleOptions = [];
+
+  function loadRoles() {
+    Cluster.getPermissions().then(function(data) {
+      $scope.roleOptions = data.map(function(item) {
+        return item.PermissionInfo;
+      });
+    });
+  }
+
+  function unsavedChangesCheck() {
+    if ($scope.form.userCreateForm.$dirty) {
+      UnsavedDialog().then(function (action) {
+        switch (action) {
+          case 'save':
+            $scope.save();
+            break;
+          case 'discard':
+            $modalInstance.close('discard');
+            break;
+          case 'cancel':
+            break;
+        }
+      });
+    } else {
+      $modalInstance.close('discard');
+    }
+  }
+
+  $scope.save = function () {
+    $scope.form.userCreateForm.submitted = true;
+    if ($scope.form.userCreateForm.$valid) {
+      User.create({
+        'Users/user_name': $scope.formData.userName,
+        'Users/password': $scope.formData.password,
+        'Users/active': Boolean($scope.formData.isActive),
+        'Users/admin': Boolean($scope.formData.isAdmin)
+      }).then(function () {
+        saveRole();
+        $modalInstance.dismiss('created');
+        Alert.success($t('users.alerts.userCreated', {
+          userName: $scope.formData.userName,
+          encUserName: encodeURIComponent($scope.formData.userName)
+        }));
+      }).catch(function (data) {
+        Alert.error($t('users.alerts.userCreationError'), data.data.message);
+      });
+    }
+  };
+
+  function saveRole() {
+    Cluster.createPrivileges(
+      {
+        clusterId: $rootScope.cluster.Clusters.cluster_name
+      },
+      [{PrivilegeInfo: {
+        permission_name: $scope.roleOptions.filter(function(role) {
+          return role.permission_id == Number($scope.formData.role);
+        })[0].permission_name,
+        principal_name: $scope.formData.userName,
+        principal_type: 'USER'
+      }}]
+    )
+    .catch(function(data) {
+      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
+    });
+  }
+
+  $scope.cancel = function () {
+    unsavedChangesCheck();
+  };
+
+  loadRoles();
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
new file mode 100644
index 0000000..001bb1b
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserEditCtrl.js
@@ -0,0 +1,290 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('UserEditCtrl', ['$scope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', function($scope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate) {
+
+  var $t = $translate.instant;
+
+  $scope.constants = {
+    user: $t('common.user'),
+    status: $t('users.status'),
+    admin: $t('users.admin'),
+    password: $t('users.password'),
+    view: $t('common.view').toLowerCase(),
+    cluster: $t('common.cluster').toLowerCase()
+  };
+
+  function loadUserInfo(){
+    User.get($routeParams.id).then(function(data) {
+      $scope.user = User.makeUser(data).Users;
+      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
+      $scope.editingGroupsList = angular.copy($scope.user.groups);
+    });
+  }
+
+  loadUserInfo();
+  $scope.user;
+  $scope.isCurrentUser = true;
+  $scope.dataLoaded = false;
+
+  $scope.isGroupEditing = false;
+  $scope.enableGroupEditing = function() {
+    $scope.isGroupEditing = true;
+    $scope.editingGroupsList = angular.copy($scope.user.groups);
+  };
+
+  $scope.$watch(function() {
+    return $scope.editingGroupsList;
+  }, function(newValue) {
+    if(newValue){
+      if( !angular.equals(newValue, $scope.user.groups) ){
+        $scope.updateGroups();
+      }
+    }
+  }, true);
+
+  $scope.updateGroups = function() {
+    var groups = $scope.editingGroupsList.toString().split(',').filter(function(item) {return item.trim();}).map(function(item) {return item.trim()});
+    var diff = getDifference($scope.user.groups, groups);
+    var promises = [];
+    // Remove user from groups
+    angular.forEach(diff.del, function(groupName) {
+      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function(data) {
+        Alert.error($t('users.alerts.removeUserError'), data.data.message);
+      }));
+    });
+    // Add user to groups
+    angular.forEach(diff.add, function(groupName) {
+      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function(data) {
+        Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
+      }));
+    });
+    $q.all(promises).then(function() {
+      loadUserInfo();
+    });
+    $scope.isGroupEditing = false;
+  };
+
+  $scope.getUserMembership = function(userType) {
+    if(userType) {
+	return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
+    }
+  };
+
+  $scope.cancelUpdate = function() {
+    $scope.isGroupEditing = false;
+    $scope.editingGroupsList = '';
+  };
+
+  $scope.openChangePwdDialog = function() {
+    var modalInstance = $modal.open({
+      templateUrl: 'views/userManagement/modals/changePassword.html',
+      resolve: {
+        userName: function() {
+          return $scope.user.user_name;
+        }
+      },
+      controller: ['$scope', 'userName', function($scope, userName) {
+        $scope.passwordData = {
+          password: '',
+          currentUserPassword: ''
+        };
+
+        $scope.form = {};
+        $scope.userName = userName;
+
+        $scope.ok = function() {
+          $scope.form.passwordChangeForm.submitted = true;
+          if($scope.form.passwordChangeForm.$valid){
+
+            modalInstance.close({
+              password: $scope.passwordData.password, 
+              currentUserPassword: $scope.passwordData.currentUserPassword
+            });
+          }
+        };
+        $scope.cancel = function() {
+          modalInstance.dismiss('cancel');
+        };
+      }]
+    });
+
+    modalInstance.result.then(function(data) {
+      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function() {
+        Alert.success($t('users.alerts.passwordChanged'));
+      }).catch(function(data) {
+        Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
+      });
+    }); 
+  };
+
+  $scope.toggleUserActive = function() {
+    if(!$scope.isCurrentUser){
+      var newStatusKey = $scope.user.active ? 'inactive' : 'active',
+        newStatus = $t('users.' + newStatusKey).toLowerCase();
+      ConfirmationModal.show(
+        $t('users.changeStatusConfirmation.title'),
+        $t('users.changeStatusConfirmation.message', {
+          userName: $scope.user.user_name,
+          status: newStatus
+        })
+      ).then(function() {
+        User.setActive($scope.user.user_name, $scope.user.active)
+          .catch(function(data) {
+            Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
+            $scope.user.active = !$scope.user.active;
+          });
+      })
+      .catch(function() {
+        $scope.user.active = !$scope.user.active;
+      });
+    }
+  };    
+  $scope.toggleUserAdmin = function() {
+    if(!$scope.isCurrentUser){
+      var action = $scope.user.admin ?
+        $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
+      ConfirmationModal.show(
+        $t('users.changePrivilegeConfirmation.title'),
+        $t('users.changePrivilegeConfirmation.message', {
+          action: action,
+          userName: $scope.user.user_name
+        })
+      ).then(function() {
+        User.setAdmin($scope.user.user_name, $scope.user.admin)
+        .then(function() {
+          loadPrivileges();
+        })
+        .catch(function (data) {
+          Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
+          $scope.user.admin = !$scope.user.admin;
+        });
+      })
+      .catch(function() {
+        $scope.user.admin = !$scope.user.admin;
+      });
+
+    }
+  };
+
+  $scope.removePrivilege = function(name, privilege) {
+    var privilegeObject = {
+        id: privilege.privilege_id,
+        view_name: privilege.view_name,
+        version: privilege.version,
+        instance_name: name
+    };
+    View.deletePrivilege(privilegeObject).then(function() {
+      loadPrivileges();
+    });
+  };
+
+  $scope.deleteUser = function() {
+    ConfirmationModal.show(
+      $t('common.delete', {
+        term: $t('common.user')
+      }),
+      $t('common.deleteConfirmation', {
+        instanceType: $t('common.user').toLowerCase(),
+        instanceName: '"' + $scope.user.user_name + '"'
+      })
+    ).then(function() {
+      Cluster.getPrivilegesForResource({
+        nameFilter : $scope.user.user_name,
+        typeFilter : {value: 'USER'}
+      }).then(function(data) {
+        var clusterPrivilegesIds = [];
+        var viewsPrivileges = [];
+        if (data.items && data.items.length) {
+          angular.forEach(data.items[0].privileges, function(privilege) {
+            if (privilege.PrivilegeInfo.principal_type === 'USER') {
+              if (privilege.PrivilegeInfo.type === 'VIEW') {
+                viewsPrivileges.push({
+                  id: privilege.PrivilegeInfo.privilege_id,
+                  view_name: privilege.PrivilegeInfo.view_name,
+                  version: privilege.PrivilegeInfo.version,
+                  instance_name: privilege.PrivilegeInfo.instance_name
+                });
+              } else {
+                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
+              }
+            }
+          });
+        }
+        User.delete($scope.user.user_name).then(function() {
+          $location.path('/userManagement');
+          if (clusterPrivilegesIds.length) {
+            Cluster.getAllClusters().then(function (clusters) {
+              var clusterName = clusters[0].Clusters.cluster_name;
+              Cluster.deleteMultiplePrivileges(clusterName, clusterPrivilegesIds);
+            });
+          }
+          angular.forEach(viewsPrivileges, function(privilege) {
+            View.deletePrivilege(privilege);
+          });
+        });
+      });
+    });
+  };
+
+  // Load privileges
+  function loadPrivileges(){
+    User.getPrivileges($routeParams.id).then(function(data) {
+      var privileges = {
+        clusters: {},
+        views: {}
+      };
+      angular.forEach(data.data.items, function(privilege) {
+        privilege = privilege.PrivilegeInfo;
+        if(privilege.type === 'CLUSTER'){
+          // This is cluster
+          if (privileges.clusters[privilege.cluster_name]) {
+            var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
+            var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
+            // replace when cur is a more powerful role
+            if (curIndex < preIndex) {
+              privileges.clusters[privilege.cluster_name] = privilege;
+            }
+          } else {
+            privileges.clusters[privilege.cluster_name] = privilege;
+          }
+        } else if ( privilege.type === 'VIEW'){
+          privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]};
+          privileges.views[privilege.instance_name].version = privilege.version;
+          privileges.views[privilege.instance_name].view_name = privilege.view_name;
+          privileges.views[privilege.instance_name].privilege_id = privilege.privilege_id;
+          if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) == -1) {
+            privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
+          }
+        }
+      });
+
+      $scope.privileges = data.data.items.length ? privileges : null;
+      $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
+      $scope.noViewPriv = $.isEmptyObject(privileges.views);
+      $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
+      $scope.dataLoaded = true;
+
+    }).catch(function(data) {
+      Alert.error($t('common.alerts.cannotLoadPrivileges'), data.data.message);
+    });
+  }
+  loadPrivileges();
+}]);

http://git-wip-us.apache.org/repos/asf/ambari/blob/99b19e58/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
new file mode 100644
index 0000000..e9ec6ab
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/userManagement/UserManagementCtrl.js
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+'use strict';
+
+angular.module('ambariAdminConsole')
+.controller('UserManagementCtrl', ['$scope', function($scope) {
+  $scope.activeTab = 'USERS';
+}]);