Kaynağa Gözat

AMBARI-7027. Config History: need current version for each config group. (myroslav via mahadev)

Mahadev Konar 10 yıl önce
ebeveyn
işleme
a8e6736ac5
15 değiştirilmiş dosya ile 214 ekleme ve 66 silme
  1. 5 5
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceConfigVersionResourceDefinition.java
  2. 13 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
  3. 6 6
      ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
  4. 6 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
  5. 9 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigGroupRequest.java
  6. 23 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
  7. 11 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java
  8. 23 17
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
  9. 4 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java
  10. 7 5
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
  11. 40 1
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java
  12. 3 3
      ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
  13. 54 13
      ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
  14. 3 2
      ambari-server/src/main/resources/properties.json
  15. 7 6
      ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java

+ 5 - 5
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceConfigVersionResourceDefinition.java

@@ -43,12 +43,12 @@ public class ServiceConfigVersionResourceDefinition extends BaseResourceDefiniti
 
   @Override
   public String getPluralName() {
-    return "serviceconfigversions";
+    return "service_config_versions";
   }
 
   @Override
   public String getSingularName() {
-    return "serviceconfigversion";
+    return "service_config_version";
   }
 
   private class HrefProcessor extends BaseHrefPostProcessor {
@@ -66,10 +66,10 @@ public class ServiceConfigVersionResourceDefinition extends BaseResourceDefiniti
         idx = href.indexOf("/", idx) + 1;
 
         String serviceName = (String) resultNode.getObject().getPropertyValue("service_name");
-        Long version = (Long) resultNode.getObject().getPropertyValue("serviceconfigversion");
+        Long version = (Long) resultNode.getObject().getPropertyValue("service_config_version");
         href = href.substring(0, idx)
-            + "configurations/serviceconfigversions?service_name="
-            + serviceName + "&serviceconfigversion=" + version;
+            + "configurations/service_config_versions?service_name="
+            + serviceName + "&service_config_version=" + version;
 
         resultNode.setProperty("href", href);
       } else {

+ 13 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -140,6 +140,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Multimaps;
 import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -1156,6 +1157,12 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       new LinkedList<ConfigurationResponse>();
     ServiceConfigVersionResponse serviceConfigVersionResponse = null;
 
+    if (request.getDesiredConfig() != null && request.getServiceConfigVersionRequest() != null) {
+      String msg = "Unable to set desired configs and rollback at same time, request = " + request.toString();
+      LOG.error(msg);
+      throw new IllegalArgumentException(msg);
+    }
+
     // set or create configuration mapping (and optionally create the map of properties)
     if (null != request.getDesiredConfig()) {
       Set<Config> configs = new HashSet<Config>();
@@ -1259,7 +1266,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         throw new IllegalArgumentException(msg);
       }
 
-      cluster.setServiceConfigVersion(serviceConfigVersionRequest.getServiceName(),
+      serviceConfigVersionResponse = cluster.setServiceConfigVersion(serviceConfigVersionRequest.getServiceName(),
           serviceConfigVersionRequest.getVersion(), getAuthName(),
           serviceConfigVersionRequest.getNote());
     }
@@ -1272,8 +1279,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       ClusterResponse clusterResponse =
           new ClusterResponse(cluster.getClusterId(), cluster.getClusterName(), null, null, null, null, null);
 
-      clusterResponse.setDesiredServiceConfigVersions(
-          Collections.singletonMap(serviceConfigVersionResponse.getServiceName(), serviceConfigVersionResponse));
+      Map<String, Collection<ServiceConfigVersionResponse>> map =
+        new HashMap<String, Collection<ServiceConfigVersionResponse>>();
+      map.put(serviceConfigVersionResponse.getServiceName(), Collections.singletonList(serviceConfigVersionResponse));
+
+      clusterResponse.setDesiredServiceConfigVersions(map);
 
       //workaround to be able to retrieve update results in resource provider
       //as this method only expected to return request response

+ 6 - 6
ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java

@@ -148,12 +148,12 @@ public class ClusterRequest {
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
-    sb.append("{"
-        + " clusterName=" + clusterName
-        + ", clusterId=" + clusterId
-        + ", provisioningState=" + provisioningState
-        + ", stackVersion=" + stackVersion
-        + ", hosts=[");
+    sb.append("{" + " clusterName=").append(clusterName)
+        .append(", clusterId=").append(clusterId)
+        .append(", provisioningState=").append(provisioningState)
+        .append(", stackVersion=").append(stackVersion)
+        .append(", desired_scv=").append(serviceConfigVersionRequest)
+        .append(", hosts=[");
     if (hostNames != null) {
       int i = 0;
       for (String hostName : hostNames) {

+ 6 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java

@@ -18,9 +18,12 @@
 
 package org.apache.ambari.server.controller;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.Multimap;
 import org.apache.ambari.server.state.DesiredConfig;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.ClusterHealthReport;
@@ -37,7 +40,7 @@ public class ClusterResponse {
 
   private Map<String, DesiredConfig> desiredConfigs;
 
-  private Map<String, ServiceConfigVersionResponse> desiredServiceConfigVersions;
+  private Map<String, Collection<ServiceConfigVersionResponse>> desiredServiceConfigVersions;
   
   private String provisioningState;
 
@@ -180,11 +183,11 @@ public class ClusterResponse {
     return clusterHealthReport;
   }
 
-  public Map<String, ServiceConfigVersionResponse> getDesiredServiceConfigVersions() {
+  public Map<String, Collection<ServiceConfigVersionResponse>> getDesiredServiceConfigVersions() {
     return desiredServiceConfigVersions;
   }
 
-  public void setDesiredServiceConfigVersions(Map<String, ServiceConfigVersionResponse> desiredServiceConfigVersions) {
+  public void setDesiredServiceConfigVersions(Map<String, Collection<ServiceConfigVersionResponse>> desiredServiceConfigVersions) {
     this.desiredServiceConfigVersions = desiredServiceConfigVersions;
   }
 }

+ 9 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigGroupRequest.java

@@ -29,6 +29,7 @@ public class ConfigGroupRequest {
   private String groupName;
   private String tag;
   private String description;
+  private String serviceConfigVersionNote;
   private Set<String> hosts;
   private Map<String, Config> configs;
 
@@ -99,4 +100,12 @@ public class ConfigGroupRequest {
   public void setId(Long id) {
     this.id = id;
   }
+
+  public String getServiceConfigVersionNote() {
+    return serviceConfigVersionNote;
+  }
+
+  public void setServiceConfigVersionNote(String serviceConfigVersionNote) {
+    this.serviceConfigVersionNote = serviceConfigVersionNote;
+  }
 }

+ 23 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java

@@ -26,6 +26,7 @@ public class ServiceConfigVersionRequest {
   private Long applyTime;
   private String userName;
   private String note;
+  private Boolean isCurrent;
 
   public ServiceConfigVersionRequest() {
   }
@@ -94,4 +95,26 @@ public class ServiceConfigVersionRequest {
   public void setNote(String note) {
     this.note = note;
   }
+
+  public Boolean getIsCurrent() {
+    return isCurrent;
+  }
+
+  public void setIsCurrent(Boolean isCurrent) {
+    this.isCurrent = isCurrent;
+  }
+
+  @Override
+  public String toString() {
+    return "ServiceConfigVersionRequest{" +
+        "clusterName='" + clusterName + '\'' +
+        ", serviceName='" + serviceName + '\'' +
+        ", version=" + version +
+        ", createTime=" + createTime +
+        ", applyTime=" + applyTime +
+        ", userName='" + userName + '\'' +
+        ", note='" + note + '\'' +
+        ", isCurrent=" + isCurrent +
+        '}';
+  }
 }

+ 11 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java

@@ -19,7 +19,6 @@
 package org.apache.ambari.server.controller;
 
 
-import org.apache.ambari.server.state.Config;
 import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
@@ -34,6 +33,7 @@ public class ServiceConfigVersionResponse {
   private String groupName;
   private String userName;
   private String note;
+  private Boolean isCurrent = false;
   private List<ConfigurationResponse> configurations;
   private List<String> hosts;
 
@@ -46,7 +46,7 @@ public class ServiceConfigVersionResponse {
     this.serviceName = serviceName;
   }
 
-  @JsonProperty("serviceconfigversion")
+  @JsonProperty("service_config_version")
   public Long getVersion() {
     return version;
   }
@@ -130,5 +130,14 @@ public class ServiceConfigVersionResponse {
   public void setGroupId(Long groupId) {
     this.groupId = groupId;
   }
+
+  @JsonProperty("is_current")
+  public Boolean getIsCurrent() {
+    return isCurrent;
+  }
+
+  public void setIsCurrent(Boolean isCurrent) {
+    this.isCurrent = isCurrent;
+  }
 }
 

+ 23 - 17
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java

@@ -64,7 +64,7 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
   protected static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version");
   protected static final String CLUSTER_PROVISIONING_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "provisioning_state");
   protected static final String CLUSTER_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_configs");
-  protected static final String CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_serviceconfigversions");
+  protected static final String CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_service_config_versions");
   protected static final String CLUSTER_TOTAL_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "total_hosts");
   protected static final String CLUSTER_HEALTH_REPORT_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "health_report");
   protected static final String BLUEPRINT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "blueprint");
@@ -173,7 +173,8 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
       setResourceProperty(resource, CLUSTER_NAME_PROPERTY_ID, clusterName, requestedIds);
       setResourceProperty(resource, CLUSTER_PROVISIONING_STATE_PROPERTY_ID, response.getProvisioningState(), requestedIds);
       setResourceProperty(resource, CLUSTER_DESIRED_CONFIGS_PROPERTY_ID, response.getDesiredConfigs(), requestedIds);
-      setResourceProperty(resource, CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID, response.getDesiredServiceConfigVersions(), requestedIds);
+      setResourceProperty(resource, CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID,
+        response.getDesiredServiceConfigVersions(), requestedIds);
       setResourceProperty(resource, CLUSTER_TOTAL_HOSTS_PROPERTY_ID, response.getTotalHosts(), requestedIds);
       setResourceProperty(resource, CLUSTER_HEALTH_REPORT_PROPERTY_ID, response.getClusterHealthReport(), requestedIds);
 
@@ -219,24 +220,29 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
     for (ClusterRequest clusterRequest : requests) {
       ClusterResponse updateResults = getManagementController().getClusterUpdateResults(clusterRequest);
       if (updateResults != null) {
-        Map<String, ServiceConfigVersionResponse> serviceConfigVersions = updateResults.getDesiredServiceConfigVersions();
+        Map<String, Collection<ServiceConfigVersionResponse>> serviceConfigVersions = updateResults.getDesiredServiceConfigVersions();
         if (serviceConfigVersions != null) {
           associatedResources = new HashSet<Resource>();
-          for (Map.Entry<String, ServiceConfigVersionResponse> stringServiceConfigVersionResponseEntry : serviceConfigVersions.entrySet()) {
-            Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
-            ServiceConfigVersionResponse serviceConfigVersionResponse = stringServiceConfigVersionResponseEntry.getValue();
-            resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID,
-              serviceConfigVersionResponse.getServiceName());
-            resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID,
-              serviceConfigVersionResponse.getVersion());
-            resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID,
-              serviceConfigVersionResponse.getNote());
-            if (serviceConfigVersionResponse.getConfigurations() != null) {
-              resource.setProperty(
+          for (Collection<ServiceConfigVersionResponse> scvCollection : serviceConfigVersions.values()) {
+            for (ServiceConfigVersionResponse serviceConfigVersionResponse : scvCollection) {
+              Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID,
+                serviceConfigVersionResponse.getServiceName());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID,
+                serviceConfigVersionResponse.getVersion());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID,
+                serviceConfigVersionResponse.getNote());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID,
+                  serviceConfigVersionResponse.getGroupId());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID,
+                  serviceConfigVersionResponse.getGroupName());
+              if (serviceConfigVersionResponse.getConfigurations() != null) {
+                resource.setProperty(
                   ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID,
                   serviceConfigVersionResponse.getConfigurations());
+              }
+              associatedResources.add(resource);
             }
-            associatedResources.add(resource);
           }
 
         }
@@ -354,13 +360,13 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
       String absCategory = PropertyHelper.getPropertyCategory(entry.getKey());
       String propName = PropertyHelper.getPropertyName(entry.getKey());
 
-      if (absCategory.startsWith(parentCategory + "/desired_serviceconfigversions")) {
+      if (absCategory.startsWith(parentCategory + "/desired_service_config_version")) {
         serviceConfigVersionRequest =
             (serviceConfigVersionRequest ==null ) ? new ServiceConfigVersionRequest() : serviceConfigVersionRequest;
 
         if (propName.equals("service_name"))
           serviceConfigVersionRequest.setServiceName(entry.getValue().toString());
-        else if (propName.equals("serviceconfigversion"))
+        else if (propName.equals("service_config_version"))
           serviceConfigVersionRequest.setVersion(Long.valueOf(entry.getValue().toString()));
         else if (propName.equals("service_config_version_note")) {
           serviceConfigVersionRequest.setNote(entry.getValue().toString());

+ 4 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java

@@ -74,6 +74,8 @@ public class ConfigGroupResourceProvider extends
     .getPropertyId("ConfigGroup", "tag");
   protected static final String CONFIGGROUP_DESC_PROPERTY_ID = PropertyHelper
     .getPropertyId("ConfigGroup", "description");
+  protected static final String CONFIGGROUP_SCV_NOTE_ID = PropertyHelper
+      .getPropertyId("ConfigGroup", "service_config_version_note");
   protected static final String CONFIGGROUP_HOSTNAME_PROPERTY_ID =
     PropertyHelper.getPropertyId(null, "host_name");
   public static final String CONFIGGROUP_HOSTS_PROPERTY_ID = PropertyHelper
@@ -595,6 +597,8 @@ public class ConfigGroupResourceProvider extends
       null,
       null);
 
+    request.setServiceConfigVersionNote((String) properties.get(CONFIGGROUP_SCV_NOTE_ID));
+
     Map<String, Config> configurations = new HashMap<String, Config>();
     Set<String> hosts = new HashSet<String>();
 

+ 7 - 5
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java

@@ -26,21 +26,21 @@ import org.apache.ambari.server.controller.ServiceConfigVersionRequest;
 import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
 import org.apache.ambari.server.controller.spi.*;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.state.Config;
 
 import java.util.*;
 
 public class ServiceConfigVersionResourceProvider extends
     AbstractControllerResourceProvider {
   public static final String SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "cluster_name");
-  public static final String SERVICE_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "serviceconfigversion");
+  public static final String SERVICE_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_config_version");
   public static final String SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_name");
   public static final String SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "createtime");
   public static final String SERVICE_CONFIG_VERSION_USER_PROPERTY_ID = PropertyHelper.getPropertyId(null, "user");
   public static final String SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_config_version_note");
   public static final String SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID = PropertyHelper.getPropertyId(null, "group_id");
   public static final String SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "group_name");
-  public static final String SERVICE_CONFIG_VERSION_HOSTNAMES_PROPERTY_ID = PropertyHelper.getPropertyId(null, "hosts");
+  public static final String SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "is_current");
+  public static final String SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId(null, "hosts");
   public static final String SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID = PropertyHelper.getPropertyId(null, "configurations");
 
   /**
@@ -106,7 +106,8 @@ public class ServiceConfigVersionResourceProvider extends
       resource.setProperty(SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID, response.getNote());
       resource.setProperty(SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID, response.getGroupId());
       resource.setProperty(SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID, response.getGroupName());
-      resource.setProperty(SERVICE_CONFIG_VERSION_HOSTNAMES_PROPERTY_ID, response.getHosts());
+      resource.setProperty(SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID, response.getHosts());
+      resource.setProperty(SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID, response.getIsCurrent());
 
       resources.add(resource);
     }
@@ -134,12 +135,13 @@ public class ServiceConfigVersionResourceProvider extends
 
     for (String propertyId : propertyIds) {
 
-      if (!propertyId.equals("cluster_name") && !propertyId.equals("serviceconfigversion") &&
+      if (!propertyId.equals("cluster_name") && !propertyId.equals("service_config_version") &&
           !propertyId.equals("service_name") && !propertyId.equals("createtime") &&
           !propertyId.equals("appliedtime") && !propertyId.equals("user") &&
           !propertyId.equals("service_config_version_note") &&
           !propertyId.equals("group_id") &&
           !propertyId.equals("group_name") &&
+          !propertyId.equals("is_current") &&
           !propertyId.equals("hosts")) {
 
         unsupportedProperties.add(propertyId);

+ 40 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java

@@ -26,7 +26,15 @@ import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 
 import javax.persistence.EntityManager;
+import javax.persistence.Tuple;
 import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+import javax.persistence.criteria.Subquery;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -66,6 +74,37 @@ public class ServiceConfigDAO {
     return maxVersions;
   }
 
+  @RequiresSession
+  public List<ServiceConfigEntity> getLastServiceConfigVersionsForGroups(Collection<Long> configGroupIds) {
+    if (configGroupIds == null || configGroupIds.isEmpty()) {
+      return Collections.emptyList();
+    }
+    CriteriaBuilder cb = entityManagerProvider.get().getCriteriaBuilder();
+    CriteriaQuery<Tuple> cq = cb.createTupleQuery();
+    Root<ServiceConfigEntity> groupVersion = cq.from(ServiceConfigEntity.class);
+
+
+    cq.multiselect(groupVersion.get("groupId").alias("groupId"), cb.max(groupVersion.<Long>get("version")).alias("lastVersion"));
+    cq.where(groupVersion.get("groupId").in(configGroupIds));
+    cq.groupBy(groupVersion.get("groupId"));
+    List<Tuple> tuples = daoUtils.selectList(entityManagerProvider.get().createQuery(cq));
+    List<ServiceConfigEntity> result = new ArrayList<ServiceConfigEntity>();
+    //subquery look to be very poor, no bulk select then, cache should help here as result size is naturally limited
+    for (Tuple tuple : tuples) {
+      CriteriaQuery<ServiceConfigEntity> sce = cb.createQuery(ServiceConfigEntity.class);
+      Root<ServiceConfigEntity> sceRoot = sce.from(ServiceConfigEntity.class);
+
+      sce.where(cb.and(cb.equal(sceRoot.get("groupId"), tuple.get("groupId")),
+        cb.equal(sceRoot.get("version"), tuple.get("lastVersion"))));
+      sce.select(sceRoot);
+      result.add(daoUtils.selectSingle(entityManagerProvider.get().createQuery(sce)));
+    }
+
+    return result;
+  }
+
+
+
   @RequiresSession
   public List<Long> getServiceConfigVersionsByConfig(Long clusterId, String configType, Long configVersion) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT scv.version " +
@@ -80,7 +119,7 @@ public class ServiceConfigDAO {
       createQuery("SELECT scv FROM ServiceConfigEntity scv " +
         "WHERE scv.clusterId = ?1 AND scv.createTimestamp = (" +
         "SELECT MAX(scv2.createTimestamp) FROM ServiceConfigEntity scv2 " +
-        "WHERE scv2.serviceName = scv.serviceName AND scv2.clusterId = ?1)",
+        "WHERE scv2.serviceName = scv.serviceName AND scv2.clusterId = ?1 AND scv2.groupId IS NULL)",
         ServiceConfigEntity.class);
 
     return daoUtils.selectList(query, clusterId);

+ 3 - 3
ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java

@@ -186,16 +186,16 @@ public interface Cluster {
    * @param version service config version
    * @param user the user making the change for audit purposes
    * @param note
-   * @return true if service config version applied
+   * @return service config version created
    * @throws AmbariException
    */
-  boolean setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException;
+  ServiceConfigVersionResponse setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException;
 
   /**
    * Get currently active service config versions for stack services
    * @return
    */
-  Map<String, ServiceConfigVersionResponse> getActiveServiceConfigVersions();
+  Map<String, Collection<ServiceConfigVersionResponse>> getActiveServiceConfigVersions();
 
   /**
    * Get service config version history

+ 54 - 13
ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java

@@ -1505,7 +1505,7 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public boolean setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException {
+  public ServiceConfigVersionResponse setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException {
     if (null == user)
       throw new NullPointerException("User must be specified.");
 
@@ -1513,9 +1513,9 @@ public class ClusterImpl implements Cluster {
     try {
       readWriteLock.writeLock().lock();
       try {
-        applyServiceConfigVersion(serviceName, version, user, note);
+        ServiceConfigVersionResponse serviceConfigVersionResponse = applyServiceConfigVersion(serviceName, version, user, note);
         configHelper.invalidateStaleConfigsCache();
-        return true;
+        return serviceConfigVersionResponse;
       } finally {
         readWriteLock.writeLock().unlock();
       }
@@ -1525,18 +1525,21 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public Map<String, ServiceConfigVersionResponse> getActiveServiceConfigVersions() {
+  public Map<String, Collection<ServiceConfigVersionResponse>> getActiveServiceConfigVersions() {
     clusterGlobalLock.readLock().lock();
     try {
       readWriteLock.readLock().lock();
       try {
-        Map<String, ServiceConfigVersionResponse> result = new HashMap<String, ServiceConfigVersionResponse>();
+        Map<String, Collection<ServiceConfigVersionResponse>> map = new HashMap<String, Collection<ServiceConfigVersionResponse>>();
 
         Set<ServiceConfigVersionResponse> responses = getActiveServiceConfigVersionSet();
         for (ServiceConfigVersionResponse response : responses) {
-          result.put(response.getServiceName(), response);
+          if (map.get(response.getServiceName()) == null) {
+            map.put(response.getServiceName(), new ArrayList<ServiceConfigVersionResponse>());
+          }
+          map.get(response.getServiceName()).add(response);
         }
-        return result;
+        return map;
       } finally {
         readWriteLock.readLock().unlock();
       }
@@ -1553,6 +1556,8 @@ public class ClusterImpl implements Cluster {
       readWriteLock.readLock().lock();
       try {
         List<ServiceConfigVersionResponse> serviceConfigVersionResponses = new ArrayList<ServiceConfigVersionResponse>();
+        Set<Long> activeIds = getActiveServiceConfigVersionIds();
+
         for (ServiceConfigEntity serviceConfigEntity : serviceConfigDAO.getServiceConfigs(getClusterId())) {
           ServiceConfigVersionResponse serviceConfigVersionResponse = new ServiceConfigVersionResponse();
 
@@ -1564,6 +1569,7 @@ public class ClusterImpl implements Cluster {
           serviceConfigVersionResponse.setNote(serviceConfigEntity.getNote());
           serviceConfigVersionResponse.setHosts(serviceConfigEntity.getHostNames());
           serviceConfigVersionResponse.setConfigurations(new ArrayList<ConfigurationResponse>());
+          serviceConfigVersionResponse.setIsCurrent(activeIds.contains(serviceConfigEntity.getServiceConfigId()));
 
           List<ClusterConfigEntity> clusterConfigEntities = serviceConfigEntity.getClusterConfigEntities();
           for (ClusterConfigEntity clusterConfigEntity : clusterConfigEntities) {
@@ -1596,16 +1602,40 @@ public class ClusterImpl implements Cluster {
     }
   }
 
-  @RequiresSession
-  Set<ServiceConfigVersionResponse> getActiveServiceConfigVersionSet() {
+  private Set<ServiceConfigVersionResponse> getActiveServiceConfigVersionSet() {
     Set<ServiceConfigVersionResponse> responses = new HashSet<ServiceConfigVersionResponse>();
-    List<ServiceConfigEntity> lastServiceConfigs = serviceConfigDAO.getLastServiceConfigs(getClusterId());
-    for (ServiceConfigEntity lastServiceConfig : lastServiceConfigs) {
-      responses.add(convertToServiceConfigVersionResponse(lastServiceConfig));
+    List<ServiceConfigEntity> activeServiceConfigVersions = getActiveServiceConfigVersionEntities();
+
+    for (ServiceConfigEntity lastServiceConfig : activeServiceConfigVersions) {
+      ServiceConfigVersionResponse response = convertToServiceConfigVersionResponse(lastServiceConfig);
+      response.setIsCurrent(true); //mark these as current, as they are
+      responses.add(response);
     }
     return responses;
   }
 
+  private Set<Long> getActiveServiceConfigVersionIds() {
+    Set<Long> idSet = new HashSet<Long>();
+    for (ServiceConfigEntity entity : getActiveServiceConfigVersionEntities()) {
+      idSet.add(entity.getServiceConfigId());
+    }
+    return idSet;
+  }
+
+  private List<ServiceConfigEntity> getActiveServiceConfigVersionEntities() {
+
+    List<ServiceConfigEntity> activeServiceConfigVersions = new ArrayList<ServiceConfigEntity>();
+    //for services
+    activeServiceConfigVersions.addAll(serviceConfigDAO.getLastServiceConfigs(getClusterId()));
+    //for config groups
+    if (clusterConfigGroups != null) {
+      activeServiceConfigVersions.addAll(
+        serviceConfigDAO.getLastServiceConfigVersionsForGroups(clusterConfigGroups.keySet()));
+    }
+
+    return activeServiceConfigVersions;
+  }
+
   @RequiresSession
   ServiceConfigVersionResponse getActiveServiceConfigVersion(String serviceName) {
     ServiceConfigEntity lastServiceConfig = serviceConfigDAO.getLastServiceConfig(getClusterId(), serviceName);
@@ -1626,11 +1656,20 @@ public class ClusterImpl implements Cluster {
     serviceConfigVersionResponse.setCreateTime(serviceConfigEntity.getCreateTimestamp());    
     serviceConfigVersionResponse.setUserName(serviceConfigEntity.getUser());
     serviceConfigVersionResponse.setNote(serviceConfigEntity.getNote());
+    if (clusterConfigGroups != null) {
+      ConfigGroup configGroup = clusterConfigGroups.get(serviceConfigEntity.getGroupId());
+      if (configGroup != null) {
+        serviceConfigVersionResponse.setGroupId(configGroup.getId());
+        serviceConfigVersionResponse.setGroupName(configGroup.getName());
+      }
+    }
+
+
     return serviceConfigVersionResponse;
   }
 
   @Transactional
-  void applyServiceConfigVersion(String serviceName, Long serviceConfigVersion, String user,
+  ServiceConfigVersionResponse applyServiceConfigVersion(String serviceName, Long serviceConfigVersion, String user,
                                  String serviceConfigVersionNote) throws AmbariException {
     ServiceConfigEntity serviceConfigEntity = serviceConfigDAO.findByServiceAndVersion(serviceName, serviceConfigVersion);
     if (serviceConfigEntity == null) {
@@ -1690,6 +1729,8 @@ public class ClusterImpl implements Cluster {
     serviceConfigEntityClone.setVersion(configVersionHelper.getNextVersion(serviceName));
 
     serviceConfigDAO.create(serviceConfigEntityClone);
+
+    return convertToServiceConfigVersionResponse(serviceConfigEntityClone);
   }
 
   @Transactional

+ 3 - 2
ambari-server/src/main/resources/properties.json

@@ -6,7 +6,7 @@
         "Clusters/version",
         "Clusters/state",
         "Clusters/desired_configs",
-        "Clusters/desired_serviceconfigversions",
+        "Clusters/desired_service_config_versions",
         "Clusters/total_hosts",
         "Clusters/health_report",
         "_"
@@ -91,7 +91,8 @@
         "ServiceConfigVersion/group_id",
         "ServiceConfigVersion/group_name",
         "ServiceConfigVersion/hosts",
-        "ServiceConfigVersion/serviceconfigversion",
+        "ServiceConfigVersion/service_config_version",
+        "ServiceConfigVersion/is_current",
         "ServiceConfigVersion/createtime",
         "ServiceConfigVersion/user",
         "ServiceConfigVersion/service_config_version_note"

+ 7 - 6
ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java

@@ -38,6 +38,7 @@ import java.util.Set;
 
 import javax.persistence.EntityManager;
 
+import com.google.common.collect.Multimap;
 import junit.framework.Assert;
 
 import org.apache.ambari.server.AmbariException;
@@ -652,11 +653,11 @@ public class ClusterTest {
       c1.getServiceConfigVersions();
     Assert.assertNotNull(serviceConfigVersions);
     Assert.assertEquals(1, serviceConfigVersions.size());
-    Map<String, ServiceConfigVersionResponse> activeServiceConfigVersions =
+    Map<String, Collection<ServiceConfigVersionResponse>> activeServiceConfigVersions =
       c1.getActiveServiceConfigVersions();
     Assert.assertEquals(1, activeServiceConfigVersions.size());
     ServiceConfigVersionResponse mapredResponse =
-      activeServiceConfigVersions.get("MAPREDUCE");
+      activeServiceConfigVersions.get("MAPREDUCE").iterator().next();
 
     Assert.assertEquals("MAPREDUCE", mapredResponse.getServiceName());
     Assert.assertEquals("c1", mapredResponse.getClusterName());
@@ -670,7 +671,7 @@ public class ClusterTest {
     Assert.assertEquals(2, serviceConfigVersions.size());
     // active version still 1
     Assert.assertEquals(1, activeServiceConfigVersions.size());
-    mapredResponse = activeServiceConfigVersions.get("MAPREDUCE");
+    mapredResponse = activeServiceConfigVersions.get("MAPREDUCE").iterator().next();
     Assert.assertEquals("MAPREDUCE", mapredResponse.getServiceName());
     Assert.assertEquals("c1", mapredResponse.getClusterName());
     Assert.assertEquals("admin", mapredResponse.getUserName());
@@ -683,7 +684,7 @@ public class ClusterTest {
     Assert.assertEquals(3, serviceConfigVersions.size());
     // active version still 1
     Assert.assertEquals(1, activeServiceConfigVersions.size());
-    mapredResponse = activeServiceConfigVersions.get("MAPREDUCE");
+    mapredResponse = activeServiceConfigVersions.get("MAPREDUCE").iterator().next();
     Assert.assertEquals("MAPREDUCE", mapredResponse.getServiceName());
     Assert.assertEquals("c1", mapredResponse.getClusterName());
     Assert.assertEquals("admin", mapredResponse.getUserName());
@@ -717,10 +718,10 @@ public class ClusterTest {
     Assert.assertEquals("version1", c1.getDesiredConfigByType("hdfs-site").getTag());
     Assert.assertEquals("version2", c1.getDesiredConfigByType("core-site").getTag());
 
-    Map<String, ServiceConfigVersionResponse> activeServiceConfigVersions =
+    Map<String, Collection<ServiceConfigVersionResponse>> activeServiceConfigVersions =
       c1.getActiveServiceConfigVersions();
     Assert.assertEquals(1, activeServiceConfigVersions.size());
 
 
   }
-}
+}