Repository: ambari
Updated Branches:
  refs/heads/trunk 1f272c278 -> 3506e4ee3


AMBARI-8464. Upgrade Execute:  support service groupings in backend (ncole)


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

Branch: refs/heads/trunk
Commit: 3506e4ee3fd1d980d05c4e81fb55ee5cb9a60702
Parents: 1f272c2
Author: Nate Cole <nc...@hortonworks.com>
Authored: Thu Nov 27 09:53:47 2014 -0500
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Mon Dec 1 10:56:57 2014 -0800

----------------------------------------------------------------------
 .../resources/ResourceInstanceFactoryImpl.java  |  12 +-
 .../UpgradeItemResourceDefinition.java          |  44 -----
 .../resources/UpgradeResourceDefinition.java    |  52 ------
 .../api/services/UpgradeGroupService.java       |  95 +++++++++++
 .../server/api/services/UpgradeItemService.java |   5 +-
 .../server/api/services/UpgradeService.java     |  10 +-
 .../internal/DefaultProviderModule.java         |   2 +
 .../internal/UpgradeGroupResourceProvider.java  | 161 +++++++++++++++++++
 .../internal/UpgradeItemResourceProvider.java   |  24 ++-
 .../internal/UpgradeResourceProvider.java       |  13 +-
 .../ambari/server/controller/spi/Resource.java  |   2 +
 .../ambari/server/orm/dao/UpgradeDAO.java       |  17 ++
 .../server/orm/entities/UpgradeEntity.java      |  13 +-
 .../server/orm/entities/UpgradeGroupEntity.java | 133 +++++++++++++++
 .../server/orm/entities/UpgradeItemEntity.java  |  26 +--
 .../server/upgrade/UpgradeCatalog200.java       |  14 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  13 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  13 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  13 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  16 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  15 +-
 .../resources/Ambari-DDL-SQLServer-DROP.sql     |   4 +-
 .../src/main/resources/META-INF/persistence.xml |   1 +
 .../internal/UpgradeResourceProviderTest.java   |  16 +-
 .../ambari/server/orm/dao/UpgradeDAOTest.java   |  20 ++-
 .../server/upgrade/UpgradeCatalog200Test.java   |   6 +
 26 files changed, 587 insertions(+), 153 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 9858e46..d0664df 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -318,11 +318,19 @@ public class ResourceInstanceFactoryImpl implements 
ResourceInstanceFactory {
         break;
 
       case Upgrade:
-        resourceDefinition = new UpgradeResourceDefinition();
+        resourceDefinition = new SimpleResourceDefinition(
+            Resource.Type.Upgrade, "upgrade", "upgrades",
+            Resource.Type.UpgradeGroup);
+        break;
+
+      case UpgradeGroup:
+        resourceDefinition = new SimpleResourceDefinition(
+            Resource.Type.UpgradeGroup, "upgrade_group", "upgrade_groups",
+            Resource.Type.UpgradeItem);
         break;
 
       case UpgradeItem:
-        resourceDefinition = new UpgradeItemResourceDefinition();
+        resourceDefinition = new 
SimpleResourceDefinition(Resource.Type.UpgradeItem, "upgrade_item", 
"upgrade_items");
         break;
 
       case Stage:

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeItemResourceDefinition.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeItemResourceDefinition.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeItemResourceDefinition.java
deleted file mode 100644
index 9ff5dee..0000000
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeItemResourceDefinition.java
+++ /dev/null
@@ -1,44 +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.
- */
-package org.apache.ambari.server.api.resources;
-
-import org.apache.ambari.server.controller.spi.Resource;
-
-/**
- * Resource Definition for {@link Resource.Type#Upgrade} types.
- */
-public class UpgradeItemResourceDefinition extends BaseResourceDefinition {
-
-  /**
-   * Constructor.
-   */
-  public UpgradeItemResourceDefinition() {
-    super(Resource.Type.UpgradeItem);
-  }
-
-  @Override
-  public String getPluralName() {
-    return "upgrade_items";
-  }
-
-  @Override
-  public String getSingularName() {
-    return "upgrade_item";
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
deleted file mode 100644
index 914e81d..0000000
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/UpgradeResourceDefinition.java
+++ /dev/null
@@ -1,52 +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.
- */
-package org.apache.ambari.server.api.resources;
-
-import java.util.Collections;
-import java.util.Set;
-
-import org.apache.ambari.server.controller.spi.Resource;
-
-/**
- * Resource Definition for {@link Resource.Type#Upgrade} types.
- */
-public class UpgradeResourceDefinition extends BaseResourceDefinition {
-
-  /**
-   * Constructor.
-   */
-  public UpgradeResourceDefinition() {
-    super(Resource.Type.Upgrade);
-  }
-
-  @Override
-  public String getPluralName() {
-    return "upgrades";
-  }
-
-  @Override
-  public String getSingularName() {
-    return "upgrade";
-  }
-
-  @Override
-  public Set<SubResourceDefinition> getSubResourceDefinitions() {
-    return Collections.singleton(new 
SubResourceDefinition(Resource.Type.UpgradeItem));
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeGroupService.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeGroupService.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeGroupService.java
new file mode 100644
index 0000000..d04e900
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeGroupService.java
@@ -0,0 +1,95 @@
+/**
+ * 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.api.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Endpoint for cluster upgrade groupings.
+ */
+public class UpgradeGroupService extends BaseService {
+
+  private String m_clusterName = null;
+  private String m_upgradeId = null;
+
+  UpgradeGroupService(String clusterName, String upgradeId) {
+    m_clusterName = clusterName;
+    m_upgradeId = upgradeId;
+  }
+
+  @GET
+  @Produces("text/plain")
+  public Response getGroups(String body,
+      @Context HttpHeaders headers,
+      @Context UriInfo ui) {
+    return handleRequest(headers, body, ui, Request.Type.GET,
+        createResourceInstance(null));
+  }
+
+  @GET
+  @Path("{upgradeGroupId}")
+  @Produces("text/plain")
+  public Response getGroup(String body,
+      @Context HttpHeaders headers,
+      @Context UriInfo ui, @PathParam("upgradeGroupId") Long id) {
+    return handleRequest(headers, body, ui, Request.Type.GET,
+        createResourceInstance(id));
+  }
+
+  @GET
+  @Path("{upgradeGroupId}/upgrade_items")
+  @Produces("text/plain")
+  public UpgradeItemService getUpgradeItems(String body,
+      @Context HttpHeaders headers,
+      @Context UriInfo ui,
+      @PathParam("upgradeGroupId") Long groupId) {
+    return new UpgradeItemService(m_clusterName, m_upgradeId, 
groupId.toString());
+  }
+
+
+
+  /**
+   * @param groupId the specific group id
+   * @return the resource instance
+   */
+  private ResourceInstance createResourceInstance(Long groupId) {
+    Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Cluster, m_clusterName);
+    mapIds.put(Resource.Type.Upgrade, m_upgradeId);
+
+    if (null != groupId) {
+      mapIds.put(Resource.Type.UpgradeGroup, groupId.toString());
+    }
+
+    return createResource(Resource.Type.UpgradeGroup, mapIds);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeItemService.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeItemService.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeItemService.java
index 0dde13b..625d47b 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeItemService.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeItemService.java
@@ -40,10 +40,12 @@ public class UpgradeItemService extends BaseService {
 
   private String m_clusterName = null;
   private String m_upgradeId = null;
+  private String m_upgradeGroupId = null;
 
-  UpgradeItemService(String clusterName, String upgradeId) {
+  UpgradeItemService(String clusterName, String upgradeId, String 
upgradeGroupId) {
     m_clusterName = clusterName;
     m_upgradeId = upgradeId;
+    m_upgradeGroupId = upgradeGroupId;
   }
 
   @GET
@@ -83,6 +85,7 @@ public class UpgradeItemService extends BaseService {
     Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
     mapIds.put(Resource.Type.Cluster, m_clusterName);
     mapIds.put(Resource.Type.Upgrade, m_upgradeId);
+    mapIds.put(Resource.Type.UpgradeGroup, m_upgradeGroupId);
 
     if (null != upgradeItemId) {
       mapIds.put(Resource.Type.UpgradeItem, upgradeItemId.toString());

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeService.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeService.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeService.java
index cd93bda..8b66491 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeService.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpgradeService.java
@@ -89,13 +89,15 @@ public class UpgradeService extends BaseService {
   }
 
   /**
-   * Gets the tasks sub-resource.
+   * Gets the groups sub-resource.
    */
-  @Path("{upgradeId}/upgrade_items")
-  public UpgradeItemService getUpgradeItemHandler(@PathParam("upgradeId") 
String upgradeId) {
-    return new UpgradeItemService(m_clusterName, upgradeId);
+  @Path("{upgradeId}/upgrade_groups")
+  public UpgradeGroupService getUpgradeGroupHandler(@PathParam("upgradeId") 
String upgradeId) {
+    return new UpgradeGroupService(m_clusterName, upgradeId);
   }
 
+
+
   /**
    * @param upgradeId the upgrade id
    * @return the resource instance

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index 83f0e0f..698737b 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -98,6 +98,8 @@ public class DefaultProviderModule extends 
AbstractProviderModule {
         return new AlertNoticeResourceProvider();
       case Upgrade:
         return new UpgradeResourceProvider(managementController);
+      case UpgradeGroup:
+        return new UpgradeGroupResourceProvider(managementController);
       case UpgradeItem:
         return new UpgradeItemResourceProvider(managementController);
       case ClusterStackVersion:

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeGroupResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeGroupResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeGroupResourceProvider.java
new file mode 100644
index 0000000..b7eb240
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeGroupResourceProvider.java
@@ -0,0 +1,161 @@
+/**
+ * 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.controller.internal;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.actionmanager.HostRoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.dao.UpgradeDAO;
+import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
+import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
+import org.apache.ambari.server.state.UpgradeState;
+
+import com.google.inject.Inject;
+
+/**
+ * Manages groupings of upgrade items.
+ */
+@StaticallyInject
+public class UpgradeGroupResourceProvider extends 
AbstractControllerResourceProvider {
+
+  protected static final String UPGRADE_ID = "UpgradeGroup/upgrade_id";
+  protected static final String UPGRADE_GROUP_ID = "UpgradeGroup/group_id";
+  protected static final String UPGRADE_GROUP_NAME = "UpgradeGroup/name";
+  protected static final String UPGRADE_GROUP_TITLE = "UpgradeGroup/title";
+  protected static final String UPGRADE_GROUP_STATE = "UpgradeGroup/state";
+
+  private static final Set<String> PK_PROPERTY_IDS = new HashSet<String>(
+      Arrays.asList(UPGRADE_ID, UPGRADE_GROUP_ID));
+  private static final Set<String> PROPERTY_IDS = new HashSet<String>();
+
+  private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new 
HashMap<Resource.Type, String>();
+
+  @Inject
+  private static UpgradeDAO m_dao = null;
+
+  static {
+    // properties
+    PROPERTY_IDS.add(UPGRADE_ID);
+    PROPERTY_IDS.add(UPGRADE_GROUP_ID);
+    PROPERTY_IDS.add(UPGRADE_GROUP_NAME);
+    PROPERTY_IDS.add(UPGRADE_GROUP_TITLE);
+
+    // keys
+    KEY_PROPERTY_IDS.put(Resource.Type.UpgradeGroup, UPGRADE_GROUP_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Upgrade, UPGRADE_ID);
+  }
+
+  /**
+   * Constructor.
+   *
+   * @param controller
+   */
+  UpgradeGroupResourceProvider(AmbariManagementController controller) {
+    super(PROPERTY_IDS, KEY_PROPERTY_IDS, controller);
+  }
+
+  @Override
+  public RequestStatus createResources(final Request request)
+      throws SystemException,
+      UnsupportedPropertyException, ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+    throw new SystemException("Upgrade Groups can only be created with an 
upgrade");
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    Set<Resource> results = new HashSet<Resource>();
+    Set<String> requestPropertyIds = getRequestPropertyIds(request, predicate);
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      String upgradeIdStr = (String) propertyMap.get(UPGRADE_ID);
+
+      if (null == upgradeIdStr || upgradeIdStr.isEmpty()) {
+        throw new IllegalArgumentException("The upgrade id is required when 
querying for upgrades");
+      }
+
+      long upgradeId = Long.parseLong(upgradeIdStr);
+      UpgradeEntity upgrade = m_dao.findUpgrade(upgradeId);
+
+      List<UpgradeGroupEntity> groups = upgrade.getUpgradeGroups();
+      if (null != groups) {
+        for (UpgradeGroupEntity group : upgrade.getUpgradeGroups()) {
+          results.add(toResource(upgrade, group, requestPropertyIds));
+        }
+      }
+
+    }
+
+    return results;
+  }
+
+  @Override
+  public RequestStatus updateResources(final Request request,
+      Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    throw new SystemException("Upgrade Items cannot be modified at this time");
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("Cannot delete upgrade items");
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return PK_PROPERTY_IDS;
+  }
+
+  private Resource toResource(UpgradeEntity upgrade, UpgradeGroupEntity group, 
Set<String> requestedIds) {
+    ResourceImpl resource = new ResourceImpl(Resource.Type.UpgradeGroup);
+
+    setResourceProperty(resource, UPGRADE_ID, upgrade.getId(), requestedIds);
+    setResourceProperty(resource, UPGRADE_GROUP_ID, group.getId(), 
requestedIds);
+    setResourceProperty(resource, UPGRADE_GROUP_NAME, group.getName(), 
requestedIds);
+    setResourceProperty(resource, UPGRADE_GROUP_TITLE, group.getTitle(), 
requestedIds);
+    setResourceProperty(resource, UPGRADE_GROUP_STATE, "NONE", requestedIds);
+
+    return resource;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
index fb7789c..d2660e0 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeItemResourceProvider.java
@@ -18,7 +18,6 @@
 package org.apache.ambari.server.controller.internal;
 
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -41,6 +40,7 @@ import 
org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
 import org.apache.ambari.server.state.UpgradeState;
 
@@ -54,6 +54,7 @@ import com.google.inject.Provider;
 public class UpgradeItemResourceProvider extends 
AbstractControllerResourceProvider {
 
   protected static final String UPGRADE_ID = "UpgradeItem/upgrade_id";
+  protected static final String UPGRADE_GROUP_ID = "UpgradeItem/group_id";
   protected static final String UPGRADE_ITEM_ID = "UpgradeItem/id";
   protected static final String UPGRADE_ITEM_STATE = "UpgradeItem/state";
   protected static final String UPGRADE_ITEM_TEXT = "UpgradeItem/text";
@@ -73,12 +74,14 @@ public class UpgradeItemResourceProvider extends 
AbstractControllerResourceProvi
   static {
     // properties
     PROPERTY_IDS.add(UPGRADE_ID);
+    PROPERTY_IDS.add(UPGRADE_GROUP_ID);
     PROPERTY_IDS.add(UPGRADE_ITEM_ID);
     PROPERTY_IDS.add(UPGRADE_ITEM_STATE);
     PROPERTY_IDS.add(UPGRADE_ITEM_TEXT);
 
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.UpgradeItem, UPGRADE_ITEM_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.UpgradeGroup, UPGRADE_GROUP_ID);
     KEY_PROPERTY_IDS.put(Resource.Type.Upgrade, UPGRADE_ID);
   }
 
@@ -109,23 +112,27 @@ public class UpgradeItemResourceProvider extends 
AbstractControllerResourceProvi
 
     for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
       String upgradeIdStr = (String) propertyMap.get(UPGRADE_ID);
+      String groupIdStr = (String) propertyMap.get(UPGRADE_GROUP_ID);
 
       if (null == upgradeIdStr || upgradeIdStr.isEmpty()) {
         throw new IllegalArgumentException("The upgrade id is required when 
querying for upgrades");
       }
 
+      if (null == groupIdStr || groupIdStr.isEmpty()) {
+        throw new IllegalArgumentException("The upgrade id is required when 
querying for upgrades");
+      }
+
+
       long upgradeId = Long.parseLong(upgradeIdStr);
-      UpgradeEntity upgrade = m_dao.findUpgrade(upgradeId);
+      long groupId = Long.parseLong(groupIdStr);
+      UpgradeGroupEntity group = m_dao.findUpgradeGroup(groupId);
 
-      if (null == upgrade) {
+      if (null == group || null == group.getItems()) {
         throw new NoSuchResourceException(String.format("Cannot load upgrade 
for %s", upgradeIdStr));
       }
 
-      Collection<UpgradeItemEntity> items = upgrade.getUpgradeItems();
-      if (null != items) {
-        for (UpgradeItemEntity entity : items) {
-          results.add(toResource(upgrade, entity, requestPropertyIds));
-        }
+      for (UpgradeItemEntity entity : group.getItems()) {
+        results.add(toResource(group.getUpgradeEntity(), entity, 
requestPropertyIds));
       }
     }
 
@@ -157,6 +164,7 @@ public class UpgradeItemResourceProvider extends 
AbstractControllerResourceProvi
     ResourceImpl resource = new ResourceImpl(Resource.Type.UpgradeItem);
 
     setResourceProperty(resource, UPGRADE_ID, upgrade.getId(), requestedIds);
+    setResourceProperty(resource, UPGRADE_GROUP_ID, 
item.getGroupEntity().getId(), requestedIds);
     setResourceProperty(resource, UPGRADE_ITEM_ID, item.getId(), requestedIds);
     if (isPropertyRequested(UPGRADE_ITEM_STATE, requestedIds)) {
       UpgradeState state = calculateState(upgrade, item);

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/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 16a8f3c..6980e15 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
@@ -56,6 +56,7 @@ import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.ConfigHelper;
@@ -70,6 +71,7 @@ import org.apache.ambari.server.utils.StageUtils;
 import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -104,8 +106,6 @@ public class UpgradeResourceProvider extends 
AbstractControllerResourceProvider
   private static Provider<AmbariActionExecutionHelper> actionExecutionHelper;
   @Inject
   private static Provider<AmbariCustomCommandExecutionHelper> 
commandExecutionHelper;
-  @Inject
-  private ConfigHelper configHelper;
 
   static {
     // properties
@@ -401,7 +401,14 @@ public class UpgradeResourceProvider extends 
AbstractControllerResourceProvider
     items = injectVariables(configHelper, cluster, items);
 
     entity.setClusterId(Long.valueOf(cluster.getClusterId()));
-    entity.setUpgradeItems(items);
+
+    // !!! a separate task will create proper groups.  for now, just one.
+    UpgradeGroupEntity group = new UpgradeGroupEntity();
+    group.setName("CLUSTER_UPGRADE");
+    group.setTitle("Cluster Upgrade");
+    group.setItems(items);
+
+    entity.setUpgradeGroups(Collections.singletonList(group));
 
     RequestStageContainer req = createRequest((String) 
requestMap.get(UPGRADE_VERSION));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 5564b31..5c9366a 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -132,6 +132,7 @@ public interface Resource {
     ClusterStackVersion,
     HostStackVersion,
     Upgrade,
+    UpgradeGroup,
     UpgradeItem,
     Stage;
 
@@ -226,6 +227,7 @@ public interface Resource {
     public static final Type ClusterStackVersion = 
InternalType.ClusterStackVersion.getType();
     public static final Type HostStackVersion = 
InternalType.HostStackVersion.getType();
     public static final Type Upgrade = InternalType.Upgrade.getType();
+    public static final Type UpgradeGroup = 
InternalType.UpgradeGroup.getType();
     public static final Type UpgradeItem = InternalType.UpgradeItem.getType();
     public static final Type Stage = InternalType.Stage.getType();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UpgradeDAO.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UpgradeDAO.java 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UpgradeDAO.java
index 6df5502..c08f809 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UpgradeDAO.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UpgradeDAO.java
@@ -24,6 +24,9 @@ import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
+import org.eclipse.persistence.config.HintValues;
+import org.eclipse.persistence.config.QueryHints;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -94,5 +97,19 @@ public class UpgradeDAO {
 
   }
 
+  /**
+   * @param groupId the group id
+   * @return the group, or {@code null} if not found
+   */
+  public UpgradeGroupEntity findUpgradeGroup(long groupId) {
+
+    TypedQuery<UpgradeGroupEntity> query = 
entityManagerProvider.get().createQuery(
+        "SELECT p FROM UpgradeGroupEntity p WHERE p.upgradeGroupId = 
:groupId", UpgradeGroupEntity.class);
+    query.setParameter("groupId", Long.valueOf(groupId));
+    query.setHint(QueryHints.REFRESH, HintValues.TRUE);
+
+    return daoUtils.selectSingle(query);
+  }
+
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
index 41346d0..2c19da3 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
@@ -33,6 +33,7 @@ import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
+import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.state.UpgradeState;
 
@@ -68,7 +69,7 @@ public class UpgradeEntity {
   private Long requestId;
 
   @OneToMany(mappedBy = "upgradeEntity", cascade = { CascadeType.ALL })
-  private List<UpgradeItemEntity> upgradeItemEntities;
+  private List<UpgradeGroupEntity> upgradeGroupEntities;
 
 
   /**
@@ -117,18 +118,18 @@ public class UpgradeEntity {
   /**
    * @return the upgrade items
    */
-  public List<UpgradeItemEntity> getUpgradeItems() {
-    return upgradeItemEntities;
+  public List<UpgradeGroupEntity> getUpgradeGroups() {
+    return upgradeGroupEntities;
   }
 
   /**
    * @param items the upgrade items
    */
-  public void setUpgradeItems(List<UpgradeItemEntity> items) {
-    for (UpgradeItemEntity entity : items) {
+  public void setUpgradeGroups(List<UpgradeGroupEntity> items) {
+    for (UpgradeGroupEntity entity : items) {
       entity.setUpgradeEntity(this);
     }
-    upgradeItemEntities = items;
+    upgradeGroupEntities = items;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeGroupEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeGroupEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeGroupEntity.java
new file mode 100644
index 0000000..534a461
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeGroupEntity.java
@@ -0,0 +1,133 @@
+/**
+ * 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.orm.entities;
+
+import java.util.List;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+/**
+ * Models a single upgrade group as part of an entire {@link UpgradeEntity}
+ */
+@Table(name = "upgrade_group")
+@Entity
+@TableGenerator(name = "upgrade_group_id_generator",
+    table = "ambari_sequences", pkColumnName = "sequence_name", 
valueColumnName = "sequence_value",
+    pkColumnValue = "upgrade_group_id_seq", initialValue = 0, allocationSize = 
1)
+public class UpgradeGroupEntity {
+
+  @Id
+  @Column(name = "upgrade_group_id", nullable = false, insertable = true, 
updatable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = 
"upgrade_group_id_generator")
+  private Long upgradeGroupId;
+
+  @Column(name = "upgrade_id", nullable = false, insertable = false, updatable 
= false)
+  private Long upgradeId;
+
+  @Basic
+  @Column(name = "group_name", length=255, nullable = false)
+  private String groupName;
+
+  @Basic
+  @Column(name = "group_title", length=1024, nullable = false)
+  private String groupTitle;
+
+
+  @ManyToOne
+  @JoinColumn(name = "upgrade_id", referencedColumnName = "upgrade_id", 
nullable = false)
+  private UpgradeEntity upgradeEntity;
+
+  @OneToMany(mappedBy ="upgradeGroupEntity", cascade = { CascadeType.ALL })
+  private List<UpgradeItemEntity> upgradeItems;
+
+
+  /**
+   * @return the id
+   */
+  public Long getId() {
+    return upgradeGroupId;
+  }
+
+  /**
+   * @param id the id
+   */
+  public void setId(Long id) {
+    upgradeGroupId = id;
+  }
+
+  /**
+   * @return the group name
+   */
+  public String getName() {
+    return groupName;
+  }
+
+  /**
+   * @param name the name
+   */
+  public void setName(String name) {
+    groupName = name;
+  }
+
+
+  /**
+   * @return the item text
+   */
+  public String getTitle() {
+    return groupTitle;
+  }
+
+  /**
+   * @param text the item text
+   */
+  public void setTitle(String title) {
+    groupTitle = title;
+  }
+
+  public UpgradeEntity getUpgradeEntity() {
+    return upgradeEntity;
+  }
+
+  public void setUpgradeEntity(UpgradeEntity entity) {
+    upgradeEntity = entity;
+  }
+
+  public List<UpgradeItemEntity> getItems() {
+    return upgradeItems;
+  }
+
+  public void setItems(List<UpgradeItemEntity> items) {
+    for (UpgradeItemEntity item : items) {
+      item.setGroupEntity(this);
+    }
+    upgradeItems = items;
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
index 2ae6944..f9336ef 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeItemEntity.java
@@ -27,14 +27,15 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
-import javax.persistence.Transient;
 
 import org.apache.ambari.server.state.UpgradeState;
 
 /**
- * Models a single upgrade item as part of an entire {@link UpgradeEntity}
+ * Models a single upgrade item as part of
  */
 @Table(name = "upgrade_item")
 @Entity
@@ -48,8 +49,8 @@ public class UpgradeItemEntity {
   @GeneratedValue(strategy = GenerationType.TABLE, generator = 
"upgrade_item_id_generator")
   private Long upgradeItemId;
 
-  @Column(name = "upgrade_id", nullable = false, insertable = false, updatable 
= false)
-  private Long upgradeId;
+  @Column(name = "upgrade_group_id", nullable = false, insertable = false, 
updatable = false)
+  private Long upgradeGroupId;
 
   @Enumerated(value=EnumType.STRING)
   @Column(name = "state", length=255, nullable = false)
@@ -72,8 +73,8 @@ public class UpgradeItemEntity {
   private Long stageId = Long.valueOf(0L);
 
   @ManyToOne
-  @JoinColumn(name = "upgrade_id", referencedColumnName = "upgrade_id", 
nullable = false)
-  private UpgradeEntity upgradeEntity;
+  @JoinColumn(name = "upgrade_group_id", referencedColumnName = 
"upgrade_group_id", nullable = false)
+  private UpgradeGroupEntity upgradeGroupEntity;
 
 
   /**
@@ -147,14 +148,15 @@ public class UpgradeItemEntity {
     itemText = text;
   }
 
-
-
-  public UpgradeEntity getUpgradeEntity() {
-    return upgradeEntity;
+  /**
+   * @return the group entity
+   */
+  public UpgradeGroupEntity getGroupEntity() {
+    return upgradeGroupEntity;
   }
 
-  public void setUpgradeEntity(UpgradeEntity entity) {
-    upgradeEntity = entity;
+  public void setGroupEntity(UpgradeGroupEntity entity) {
+    upgradeGroupEntity = entity;
   }
 
   public Long getStageId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
index a6157fb..004d213 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
@@ -188,15 +188,25 @@ public class UpgradeCatalog200 extends 
AbstractUpgradeCatalog {
     dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, 
sequence_value) VALUES('upgrade_id_seq', 0)", false);
 
     columns = new ArrayList<DBColumnInfo>();
-    columns.add(new DBAccessor.DBColumnInfo("upgrade_item_id", Long.class, 
null, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("upgrade_group_id", Long.class, 
null, null, false));
     columns.add(new DBAccessor.DBColumnInfo("upgrade_id", Long.class, null, 
null, false));
+    columns.add(new DBAccessor.DBColumnInfo("group_name", String.class, 255, 
"", false));
+    columns.add(new DBAccessor.DBColumnInfo("group_title", String.class, 1024, 
"", false));
+    dbAccessor.createTable("upgrade_group", columns, "upgrade_group_id");
+    dbAccessor.addFKConstraint("upgrade_group", "fk_upgrade_group_upgrade_id", 
"upgrade_id", "upgrade", "upgrade_id", false);
+    dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, 
sequence_value) VALUES('upgrade_group_id_seq', 0)", false);
+
+
+    columns = new ArrayList<DBColumnInfo>();
+    columns.add(new DBAccessor.DBColumnInfo("upgrade_item_id", Long.class, 
null, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("upgrade_group_id", Long.class, 
null, null, false));
     columns.add(new DBAccessor.DBColumnInfo("stage_id", Long.class, null, 
null, false));
     columns.add(new DBAccessor.DBColumnInfo("state", String.class, 255, 
UpgradeState.NONE.name(), false));
     columns.add(new DBAccessor.DBColumnInfo("hosts", char[].class, 32672, 
null, true));
     columns.add(new DBAccessor.DBColumnInfo("tasks", char[].class, 32672, 
null, true));
     columns.add(new DBAccessor.DBColumnInfo("item_text", String.class, 1024, 
null, true));
     dbAccessor.createTable("upgrade_item", columns, "upgrade_item_id");
-    dbAccessor.addFKConstraint("upgrade", "fk_upgrade_item_upgrade_id", 
"upgrade_id", "upgrade", "upgrade_id", false);
+    dbAccessor.addFKConstraint("upgrade_item", 
"fk_upgrade_item_upgrade_group_id", "upgrade_group_id", "upgrade_group", 
"upgrade_group_id", false);
     dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, 
sequence_value) VALUES('upgrade_item_id_seq', 0)", false);
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 110abe0..4bd374d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -707,16 +707,25 @@ CREATE TABLE upgrade (
   FOREIGN KEY (request_id) REFERENCES request(request_id)
 );
 
+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,
+  PRIMARY KEY (upgrade_group_id),
+  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+);
+
 CREATE TABLE upgrade_item (
   upgrade_item_id BIGINT NOT NULL,
-  upgrade_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 VARCHAR(1024),
   PRIMARY KEY (upgrade_item_id),
-  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+  FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
 -- In order for the first ID to be 1, must initialize the ambari_sequences 
table with a sequence_value of 0.

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 9e4cad3..9eb4e3a 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -697,16 +697,25 @@ CREATE TABLE upgrade (
   FOREIGN KEY (request_id) REFERENCES request(request_id)
 );
 
+CREATE TABLE upgrade_group (
+  upgrade_group_id BIGINT NOT NULL,
+  upgrade_id BIGINT NOT NULL,
+  group_name VARCHAR2(255) DEFAULT '' NOT NULL,
+  group_title VARCHAR2(1024) DEFAULT '' NOT NULL,
+  PRIMARY KEY (upgrade_group_id),
+  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+);
+
 CREATE TABLE upgrade_item (
   upgrade_item_id BIGINT NOT NULL,
-  upgrade_id BIGINT NOT NULL,
+  upgrade_group_id BIGINT NOT NULL,
   stage_id BIGINT NOT NULL,
   state VARCHAR2(255) DEFAULT 'NONE' NOT NULL,
   hosts CLOB,
   tasks CLOB,
   item_text VARCHAR2(1024),
   PRIMARY KEY (upgrade_item_id),
-  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+  FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 92e9170..e8f20f6 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -694,16 +694,25 @@ CREATE TABLE upgrade (
   FOREIGN KEY (request_id) REFERENCES request(request_id)
 );
 
+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,
+  PRIMARY KEY (upgrade_group_id),
+  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+);
+
 CREATE TABLE upgrade_item (
   upgrade_item_id BIGINT NOT NULL,
-  upgrade_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 VARCHAR(1024),
   PRIMARY KEY (upgrade_item_id),
-  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+  FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
 ---------inserting some data-----------

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index a35d33e..059662f 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -777,19 +777,29 @@ CREATE TABLE ambari.upgrade (
   FOREIGN KEY (request_id) REFERENCES ambari.request(request_id)
 );
 
+CREATE TABLE ambari.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,
+  PRIMARY KEY (upgrade_group_id),
+  FOREIGN KEY (upgrade_id) REFERENCES ambari.upgrade(upgrade_id)
+);
+
 CREATE TABLE ambari.upgrade_item (
   upgrade_item_id BIGINT NOT NULL,
-  upgrade_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 VARCHAR(1024),
   PRIMARY KEY (upgrade_item_id),
-  FOREIGN KEY (upgrade_id) REFERENCES ambari.upgrade(upgrade_id)
+  FOREIGN KEY (upgrade_group_id) REFERENCES 
ambari.upgrade_group(upgrade_group_id)
 );
 
 GRANT ALL PRIVILEGES ON TABLE ambari.upgrade TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.upgrade_group TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.upgrade_item TO :username;
 
 ---------inserting some data-----------
@@ -854,6 +864,8 @@ INSERT INTO ambari.ambari_sequences (sequence_name, 
sequence_value)
   union all
   select 'upgrade_id_seq', 0 
   union all
+  select 'upgrade_group_id_seq', 0 
+  union all
   select 'upgrade_item_id_seq', 0;
 
 INSERT INTO ambari.adminresourcetype (resource_type_id, resource_type_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index f553f6e..232b283 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -279,16 +279,25 @@ CREATE TABLE upgrade (
   FOREIGN KEY (request_id) REFERENCES request(request_id)
 );
 
+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,
+  PRIMARY KEY (upgrade_group_id),
+  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+);
+
 CREATE TABLE upgrade_item (
   upgrade_item_id BIGINT NOT NULL,
-  upgrade_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 VARCHAR(1024),
   PRIMARY KEY (upgrade_item_id),
-  FOREIGN KEY (upgrade_id) REFERENCES upgrade(upgrade_id)
+  FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
 ---------inserting some data-----------
@@ -734,4 +743,4 @@ BEGIN
     from task t inner join deleted d on t.taskId = d.taskId
 END
 
-GO
\ No newline at end of file
+GO

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/Ambari-DDL-SQLServer-DROP.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-DROP.sql 
b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-DROP.sql
index 45b3168..63b88ee 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-DROP.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-DROP.sql
@@ -129,6 +129,8 @@ IF OBJECT_ID('stage', 'U') IS NOT NULL DROP TABLE stage
 GO
 IF OBJECT_ID('upgrade_item', 'U') IS NOT NULL DROP TABLE upgrade_item
 GO
+IF OBJECT_ID('upgrade_group', 'U') IS NOT NULL DROP TABLE upgrade_group
+GO
 IF OBJECT_ID('upgrade', 'U') IS NOT NULL DROP TABLE upgrade
 GO
 IF OBJECT_ID('requestoperationlevel', 'U') IS NOT NULL DROP TABLE 
requestoperationlevel
@@ -202,4 +204,4 @@ GO
 IF OBJECT_ID('adminprincipal', 'U') IS NOT NULL DROP TABLE adminprincipal
 GO
 IF OBJECT_ID('adminprincipaltype', 'U') IS NOT NULL DROP TABLE 
adminprincipaltype
-GO
\ No newline at end of file
+GO

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml 
b/ambari-server/src/main/resources/META-INF/persistence.xml
index d0e662c..dc49b7c 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -65,6 +65,7 @@
     
<class>org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.StageEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeEntity</class>
+    <class>org.apache.ambari.server.orm.entities.UpgradeGroupEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeItemEntity</class>
     <class>org.apache.ambari.server.orm.entities.UserEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntity</class>

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
index 046a69b..75e6e73 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
@@ -38,6 +38,7 @@ import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -145,11 +146,16 @@ public class UpgradeResourceProviderTest {
 
     UpgradeEntity entity = upgrades.get(0);
     assertEquals(cluster.getClusterId(), entity.getClusterId().longValue());
-    assertEquals(3, entity.getUpgradeItems().size());
 
-    
assertTrue(entity.getUpgradeItems().get(0).getText().contains("Preparing"));
-    
assertTrue(entity.getUpgradeItems().get(1).getText().contains("Restarting"));
-    
assertTrue(entity.getUpgradeItems().get(2).getText().contains("Finalizing"));
+    assertEquals(1, entity.getUpgradeGroups().size());
+
+    UpgradeGroupEntity group = entity.getUpgradeGroups().get(0);
+
+    assertEquals(3, group.getItems().size());
+
+    assertTrue(group.getItems().get(0).getText().contains("Preparing"));
+    assertTrue(group.getItems().get(1).getText().contains("Restarting"));
+    assertTrue(group.getItems().get(2).getText().contains("Finalizing"));
 
     ActionManager am = injector.getInstance(ActionManager.class);
     List<Long> requests = am.getRequestsByStatus(RequestStatus.IN_PROGRESS, 
100, true);
@@ -162,7 +168,7 @@ public class UpgradeResourceProviderTest {
     assertEquals(3, stages.size());
     for (int i = 0; i < stages.size(); i++) {
       Stage stage = stages.get(i);
-      UpgradeItemEntity upgradeItem = entity.getUpgradeItems().get(i);
+      UpgradeItemEntity upgradeItem = group.getItems().get(i);
       assertEquals(stage.getStageId(), upgradeItem.getStageId().longValue());
       assertEquals(UpgradeState.NONE, upgradeItem.getState());
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
index 4848428..113de2d 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
@@ -30,9 +31,11 @@ import 
org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
 import org.apache.ambari.server.state.UpgradeState;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -71,6 +74,10 @@ public class UpgradeDAOTest {
     entity.setClusterId(Long.valueOf(1));
     entity.setRequestId(Long.valueOf(1));
 
+    UpgradeGroupEntity group = new UpgradeGroupEntity();
+    group.setName("group_name");
+    group.setTitle("group title");
+
     // create 2 items
     List<UpgradeItemEntity> items = new ArrayList<UpgradeItemEntity>();
     UpgradeItemEntity item = new UpgradeItemEntity();
@@ -83,8 +90,8 @@ public class UpgradeDAOTest {
     item.setStageId(Long.valueOf(1L));
     items.add(item);
 
-
-    entity.setUpgradeItems(items);
+    group.setItems(items);
+    entity.setUpgradeGroups(Collections.singletonList(group));
     dao.create(entity);
   }
 
@@ -108,6 +115,15 @@ public class UpgradeDAOTest {
 
     UpgradeEntity entity = dao.findUpgrade(items.get(0).getId().longValue());
     assertNotNull(entity);
+    assertEquals(1, entity.getUpgradeGroups().size());
+
+    UpgradeGroupEntity group = dao.findUpgradeGroup(
+        entity.getUpgradeGroups().get(0).getId().longValue());
+
+    assertNotNull(group);
+    Assert.assertNotSame(entity.getUpgradeGroups().get(0), group);
+    assertEquals("group_name", group.getName());
+    assertEquals("group title", group.getTitle());
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/3506e4ee/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
index 5f0b03a..1545a03 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
@@ -101,6 +101,7 @@ public class UpgradeCatalog200Test {
     Capture<List<DBAccessor.DBColumnInfo>> alertTargetStatesCapture = new 
Capture<List<DBAccessor.DBColumnInfo>>();
 
     Capture<List<DBAccessor.DBColumnInfo>> upgradeCapture = new 
Capture<List<DBAccessor.DBColumnInfo>>();
+    Capture<List<DBAccessor.DBColumnInfo>> upgradeGroupCapture = new 
Capture<List<DBAccessor.DBColumnInfo>>();
     Capture<List<DBAccessor.DBColumnInfo>> upgradeItemCapture = new 
Capture<List<DBAccessor.DBColumnInfo>>();
 
     // Alert Definition
@@ -140,9 +141,13 @@ public class UpgradeCatalog200Test {
     // Upgrade
     dbAccessor.createTable(eq("upgrade"), capture(upgradeCapture), 
eq("upgrade_id"));
 
+    // Upgrade Group item
+    dbAccessor.createTable(eq("upgrade_group"), capture(upgradeGroupCapture), 
eq("upgrade_group_id"));
+
     // Upgrade item
     dbAccessor.createTable(eq("upgrade_item"), capture(upgradeItemCapture), 
eq("upgrade_item_id"));
 
+
     setViewInstancePropertyExpectations(dbAccessor, valueColumnCapture);
     setViewInstanceDataExpectations(dbAccessor, dataValueColumnCapture);
 
@@ -185,6 +190,7 @@ public class UpgradeCatalog200Test {
     assertViewInstanceDataColumns(dataValueColumnCapture);
 
     assertEquals(4, upgradeCapture.getValue().size());
+    assertEquals(4, upgradeGroupCapture.getValue().size());
     assertEquals(7, upgradeItemCapture.getValue().size());
   }
 

Reply via email to