You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by js...@apache.org on 2014/12/11 03:29:22 UTC

[3/3] ambari git commit: AMBARI-7202: Add functionality for Ambari Common Services

AMBARI-7202: Add functionality for Ambari Common Services


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

Branch: refs/heads/trunk
Commit: 14c869961a4bc5cb9ffa041d8ef79ade3ffff3bb
Parents: f6248ae
Author: Jayush Luniya <jl...@hortonworks.com>
Authored: Wed Dec 10 21:24:53 2014 -0500
Committer: John Speidel <js...@hortonworks.com>
Committed: Wed Dec 10 21:26:43 2014 -0500

----------------------------------------------------------------------
 ambari-server/conf/unix/ambari.properties       |   1 +
 ambari-server/conf/windows/ambari.properties    |   1 +
 .../server/api/services/AmbariMetaInfo.java     |  10 +-
 .../server/configuration/Configuration.java     |   9 +
 .../apache/ambari/server/stack/BaseModule.java  |  28 +-
 .../ambari/server/stack/ComponentModule.java    |   2 +-
 .../server/stack/ConfigurationModule.java       |   2 +-
 .../apache/ambari/server/stack/ModuleState.java |  29 ++
 .../ambari/server/stack/ServiceModule.java      |  85 +++-
 .../server/stack/StackDefinitionModule.java     |  17 +-
 .../ambari/server/stack/StackManager.java       | 176 ++++++--
 .../apache/ambari/server/stack/StackModule.java | 193 ++++++---
 .../server/api/services/AmbariMetaInfoTest.java |   2 +-
 .../services/KerberosServiceMetaInfoTest.java   |   2 +-
 .../AmbariManagementControllerTest.java         |   2 +-
 .../server/stack/ComponentModuleTest.java       |   2 +-
 .../ambari/server/stack/ServiceModuleTest.java  |   2 +-
 .../stack/StackManagerCommonServicesTest.java   | 167 ++++++++
 .../server/stack/StackManagerMiscTest.java      |  91 +++++
 .../ambari/server/stack/StackManagerTest.java   |  80 +---
 .../HBASE/1.0/configuration/hbase-site.xml      | 137 +++++++
 .../common-services/HBASE/1.0/metainfo.xml      | 121 ++++++
 .../HDFS/1.0/configuration/hbase-site.xml       | 137 +++++++
 .../HDFS/1.0/configuration/hdfs-site.xml        | 396 ++++++++++++++++++
 .../common-services/HDFS/1.0/metainfo.xml       | 133 ++++++
 .../common-services/HIVE/1.0/metainfo.xml       | 127 ++++++
 .../MAPREDUCE/1.0/configuration/hbase-site.xml  | 137 +++++++
 .../MAPREDUCE/1.0/configuration/hdfs-site.xml   | 396 ++++++++++++++++++
 .../MAPREDUCE/1.0/configuration/mapred-site.xml | 400 +++++++++++++++++++
 .../common-services/MAPREDUCE/1.0/metainfo.xml  |  89 +++++
 .../PIG/1.0/configuration/pig.properties        |  52 +++
 .../common-services/PIG/1.0/metainfo.xml        |  61 +++
 .../common-services/ZOOKEEPER/1.0/metainfo.xml  |  72 ++++
 .../HDP/0.1/metainfo.xml                        |  22 +
 .../HDP/0.1/repos/repoinfo.xml                  |  57 +++
 .../HDP/0.1/services/HDFS/metainfo.xml          |  46 +++
 .../HDP/0.1/services/MAPREDUCE/metainfo.xml     |  23 ++
 .../HDP/0.1/services/PIG/metainfo.xml           |  26 ++
 .../HDP/0.2/metainfo.xml                        |  22 +
 .../HDP/0.2/repos/repoinfo.xml                  |  57 +++
 .../HDP/0.2/services/HBASE/metainfo.xml         |  26 ++
 .../0.2/services/HDFS/configuration/global.xml  | 145 +++++++
 .../services/HDFS/configuration/hadoop-env.xml  | 223 +++++++++++
 .../services/HDFS/configuration/hbase-site.xml  | 137 +++++++
 .../services/HDFS/configuration/hdfs-log4j.xml  | 199 +++++++++
 .../services/HDFS/configuration/hdfs-site.xml   | 396 ++++++++++++++++++
 .../HDP/0.2/services/HDFS/metainfo.xml          |  30 ++
 .../HDP/0.2/services/HIVE/metainfo.xml          |  26 ++
 .../HDP/0.2/services/MAPREDUCE/metainfo.xml     |  23 ++
 .../HDP/0.2/services/ZOOKEEPER/metainfo.xml     |  26 ++
 50 files changed, 4452 insertions(+), 191 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/conf/unix/ambari.properties
----------------------------------------------------------------------
diff --git a/ambari-server/conf/unix/ambari.properties b/ambari-server/conf/unix/ambari.properties
index 9ef645b..fd1818b 100644
--- a/ambari-server/conf/unix/ambari.properties
+++ b/ambari-server/conf/unix/ambari.properties
@@ -27,6 +27,7 @@ jce_policy1.6.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jce_policy-6.zi
 jdk1.7.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-7u67-linux-x64.tar.gz
 jce_policy1.7.url=http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip
 metadata.path=/var/lib/ambari-server/resources/stacks
+common.services.path=
 server.version.file=/var/lib/ambari-server/resources/version
 webapp.dir=/usr/lib/ambari-server/web
 bootstrap.dir=/var/run/ambari-server/bootstrap

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/conf/windows/ambari.properties
----------------------------------------------------------------------
diff --git a/ambari-server/conf/windows/ambari.properties b/ambari-server/conf/windows/ambari.properties
index fd3a7ba..8939b73 100644
--- a/ambari-server/conf/windows/ambari.properties
+++ b/ambari-server/conf/windows/ambari.properties
@@ -32,6 +32,7 @@ jdk1.7.67.jcpol-file=UnlimitedJCEPolicyJDK7.zip
 jdk1.7.67.home=C:\\jdk1.7.0_67
 
 metadata.path=resources\\stacks
+common.services.path=
 server.version.file=version
 webapp.dir=web
 bootstrap.dir=bootstrap

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index 8d404ca..60d4f9b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@ -124,6 +124,7 @@ public class AmbariMetaInfo {
   private StackManager stackManager;
 
   private File stackRoot;
+  private File commonServicesRoot;
   private File serverVersionFile;
   private File customActionRoot;
 
@@ -173,16 +174,21 @@ public class AmbariMetaInfo {
   @Inject
   public AmbariMetaInfo(Configuration conf) throws Exception {
     String stackPath = conf.getMetadataPath();
+    String commonServicesPath = conf.getCommonServicesPath();
     String serverVersionFilePath = conf.getServerVersionFilePath();
     stackRoot = new File(stackPath);
+    if(commonServicesPath != null && !commonServicesPath.isEmpty()) {
+      commonServicesRoot = new File(commonServicesPath);
+    }
     serverVersionFile = new File(serverVersionFilePath);
     customActionRoot = new File(conf.getCustomActionDefinitionPath());
     os_family = new OsFamily(conf);
     ALL_SUPPORTED_OS = new ArrayList<String>(os_family.os_list());
   }
 
-  public AmbariMetaInfo(File stackRoot, File serverVersionFile) throws Exception {
+  public AmbariMetaInfo(File stackRoot, File commonServicesRoot, File serverVersionFile) throws Exception {
     this.stackRoot = stackRoot;
+    this.commonServicesRoot = commonServicesRoot;
     this.serverVersionFile = serverVersionFile;
   }
 
@@ -196,7 +202,7 @@ public class AmbariMetaInfo {
     // Need to be initialized before all actions
     ALL_SUPPORTED_OS = new ArrayList<String>(os_family.os_list());
     readServerVersion();
-    stackManager = new StackManager(stackRoot,
+    stackManager = new StackManager(stackRoot,commonServicesRoot,
         new StackContext(metaInfoDAO, actionMetadata, os_family));
     getCustomActionDefinitions(customActionRoot);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index da55868..4bbe255 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -98,6 +98,7 @@ public class Configuration {
   public static final String SRVR_DISABLED_PROTOCOLS = "security.server.disabled.protocols";
   public static final String RESOURCES_DIR_KEY = "resources.dir";
   public static final String METADETA_DIR_PATH = "metadata.path";
+  public static final String COMMON_SERVICES_DIR_PATH = "common.services.path";
   public static final String SERVER_VERSION_FILE = "server.version.file";
   public static final String SERVER_VERSION_KEY = "version";
   public static final String JAVA_HOME_KEY = "java.home";
@@ -679,6 +680,14 @@ public class Configuration {
     return properties.getProperty(METADETA_DIR_PATH);
   }
 
+  /**
+   * Gets ambari common services path
+   * @return String
+   */
+  public String getCommonServicesPath() {
+    return properties.getProperty(COMMON_SERVICES_DIR_PATH);
+  }
+
   public String getServerVersionFilePath() {
     return properties.getProperty(SERVER_VERSION_FILE);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
index b27adea..ef2438f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
@@ -31,28 +31,46 @@ import java.util.Set;
  * Provides functionality that is common across multiple modules.
  */
 public abstract class BaseModule<T, I> implements StackDefinitionModule<T, I> {
+
+  /**
+   * Module visitation state
+   */
+  protected ModuleState moduleState = ModuleState.INIT;
+
+  /**
+   * Module state.
+   * Initial state is INIT.
+   * When resolve is called state is set to VISITED.
+   * When resolve completes, state is set to RESOLVED.
+   *
+   * @return the module's state
+   */
+  public ModuleState getModuleState() {
+    return moduleState;
+  }
+
   /**
    * Merges child modules with the corresponding parent modules.
    *
    * @param allStacks      collection of all stack module in stack definition
+   * @param commonServices collection of all common service module in stack definition
    * @param modules        child modules of this module that are to be merged
    * @param parentModules  parent modules which the modules are to be merged with
    *
    * @return collection of the merged modules
    */
   protected <T extends StackDefinitionModule<T, ?>> Collection<T> mergeChildModules(
-      Map<String, StackModule> allStacks, Map<String, T> modules, Map<String, T> parentModules)
+      Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, T> modules, Map<String, T> parentModules)
         throws AmbariException {
-
     Set<String> addedModules = new HashSet<String>();
     Collection<T> mergedModules = new HashSet<T>();
 
     for (T module : modules.values()) {
       String id = module.getId();
       addedModules.add(id);
-      if (! module.isDeleted()) {
+      if (!module.isDeleted()) {
         if (parentModules.containsKey(id)) {
-          module.resolve(parentModules.get(id), allStacks);
+          module.resolve(parentModules.get(id), allStacks, commonServices);
         }
         mergedModules.add(module);
       }
@@ -61,7 +79,7 @@ public abstract class BaseModule<T, I> implements StackDefinitionModule<T, I> {
     // add non-overlapping parent modules
     for (T parentModule : parentModules.values()) {
       String id = parentModule.getId();
-      if (! addedModules.contains(id)) {
+      if (!addedModules.contains(id)) {
         mergedModules.add(parentModule);
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
index 0f2a691..f4e9999 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
@@ -47,7 +47,7 @@ public class ComponentModule extends BaseModule<ComponentModule, ComponentInfo>
   }
 
   @Override
-  public void resolve(ComponentModule parent, Map<String, StackModule> allStacks) {
+  public void resolve(ComponentModule parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) {
     ComponentInfo parentInfo = parent.getModuleInfo();
 
     if (componentInfo.getCommandScript() == null) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationModule.java
index ff2e930..fde7b2d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationModule.java
@@ -61,7 +61,7 @@ public class ConfigurationModule extends BaseModule<ConfigurationModule, Configu
   }
 
   @Override
-  public void resolve(ConfigurationModule parent, Map<String, StackModule> allStacks) throws AmbariException {
+  public void resolve(ConfigurationModule parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) throws AmbariException {
     // merge properties also removes deleted props so should be called even if extension is disabled
     mergeProperties(parent);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/ModuleState.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ModuleState.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ModuleState.java
new file mode 100644
index 0000000..74e3a78
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ModuleState.java
@@ -0,0 +1,29 @@
+/**
+ * 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.stack;
+
+/**
+ * Module visitation state enum used for cycle detection
+ */
+public enum ModuleState
+{
+  INIT,
+  VISITED,
+  RESOLVED
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
index c783676..d025946 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
@@ -63,6 +63,10 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
    */
   private ServiceDirectory serviceDirectory;
 
+  /**
+   * Flag to mark a service as a common service
+   */
+  private boolean isCommonService;
 
   /**
    * Constructor.
@@ -72,9 +76,23 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
    * @param serviceDirectory  used for all IO interaction with service directory in stack definition
    */
   public ServiceModule(StackContext stackContext, ServiceInfo serviceInfo, ServiceDirectory serviceDirectory) {
+    this(stackContext, serviceInfo, serviceDirectory, false);
+  }
+
+  /**
+   * Constructor.
+   *
+   * @param stackContext      stack context which provides module access to external functionality
+   * @param serviceInfo       associated service info
+   * @param serviceDirectory  used for all IO interaction with service directory in stack definition
+   * @param isCommonService   flag to mark a service as a common service
+   */
+  public ServiceModule(
+      StackContext stackContext, ServiceInfo serviceInfo, ServiceDirectory serviceDirectory, boolean isCommonService) {
     this.serviceInfo = serviceInfo;
     this.stackContext = stackContext;
     this.serviceDirectory = serviceDirectory;
+    this.isCommonService = isCommonService;
 
     serviceInfo.setMetricsFile(serviceDirectory.getMetricsFile());
     serviceInfo.setAlertsFile(serviceDirectory.getAlertsFile());
@@ -91,7 +109,9 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
   }
 
   @Override
-  public void resolve(ServiceModule parentModule, Map<String, StackModule> allStacks) throws AmbariException {
+  public void resolve(
+      ServiceModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
     ServiceInfo parent = parentModule.getModuleInfo();
 
     if (serviceInfo.getComment() == null) {
@@ -135,8 +155,46 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
 
     mergeCustomCommands(parent.getCustomCommands(), serviceInfo.getCustomCommands());
     mergeConfigDependencies(parent);
-    mergeComponents(parentModule, allStacks);
-    mergeConfigurations(parentModule, allStacks);
+    mergeComponents(parentModule, allStacks, commonServices);
+    mergeConfigurations(parentModule, allStacks, commonServices);
+  }
+
+  /**
+   * Resolve common service
+   * @param allStacks       all stack modules
+   * @param commonServices  common service modules
+   *
+   * @throws AmbariException
+   */
+  public void resolveCommonService(Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
+    if(!isCommonService) {
+      throw new AmbariException("Not a common service");
+    }
+    moduleState = ModuleState.VISITED;
+    String parentString = serviceInfo.getParent();
+    if(parentString != null) {
+      String[] parentToks = parentString.split(StackManager.PATH_DELIMITER);
+      if(parentToks.length != 3) {
+        throw new AmbariException("The common service '" + serviceInfo.getName() + serviceInfo.getVersion()
+            + "' extends an invalid parent: '" + parentString + "'");
+      }
+      if (parentToks[0].equalsIgnoreCase(StackManager.COMMON_SERVICES)) {
+        String baseServiceKey = parentToks[1] + StackManager.PATH_DELIMITER + parentToks[2];
+        ServiceModule baseService = commonServices.get(baseServiceKey);
+        ModuleState baseModuleState = baseService.getModuleState();
+        if (baseModuleState == ModuleState.INIT) {
+          baseService.resolveCommonService(allStacks, commonServices);
+        } else if (baseModuleState == ModuleState.VISITED) {
+          //todo: provide more information to user about cycle
+          throw new AmbariException("Cycle detected while parsing common service");
+        }
+        resolve(baseService, allStacks, commonServices);
+      } else {
+        throw new AmbariException("Common service cannot inherit from a non common service");
+      }
+    }
+    moduleState = ModuleState.RESOLVED;
   }
 
   @Override
@@ -222,15 +280,18 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
    * Merge configurations with the parent configurations.
    * This will update the child configuration module set as well as the underlying info instances.
    *
-   * @param parent  parent service module
-   * @param stacks  all stack modules
+   * @param parent          parent service module
+   * @param allStacks       all stack modules
+   * @param commonServices  common service modules
    */
-  private void mergeConfigurations(ServiceModule parent, Map<String, StackModule> stacks) throws AmbariException {
+  private void mergeConfigurations(
+      ServiceModule parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
     serviceInfo.getProperties().clear();
     serviceInfo.setAllConfigAttributes(new HashMap<String, Map<String, Map<String, String>>>());
 
     Collection<ConfigurationModule> mergedModules = mergeChildModules(
-        stacks, configurationModules, parent.configurationModules);
+        allStacks, commonServices, configurationModules, parent.configurationModules);
 
     for (ConfigurationModule module : mergedModules) {
       configurationModules.put(module.getId(), module);
@@ -242,11 +303,17 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
   /**
    * Merge components with the parent configurations.
    * This will update the child component module set as well as the underlying info instances.
+   *
+   * @param parent          parent service module
+   * @param allStacks       all stack modules
+   * @param commonServices  common service modules
    */
-  private void mergeComponents(ServiceModule parent, Map<String, StackModule> stacks) throws AmbariException {
+  private void mergeComponents(
+      ServiceModule parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
     serviceInfo.getComponents().clear();
     Collection<ComponentModule> mergedModules = mergeChildModules(
-        stacks, componentModules, parent.componentModules);
+        allStacks, commonServices, componentModules, parent.componentModules);
 
     for (ComponentModule module : mergedModules) {
       componentModules.put(module.getId(), module);

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDefinitionModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDefinitionModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDefinitionModule.java
index cc088e3..f938ba8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDefinitionModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDefinitionModule.java
@@ -34,12 +34,13 @@ public interface StackDefinitionModule <T, I> {
   /**
    * Resolve the module state with the specified parent.
    *
-   * @param parent     the parent that this module will be merged with
-   * @param allStacks  collection of all stack modules in the tree
+   * @param parent          the parent that this module will be merged with
+   * @param allStacks       collection of all stack modules in the tree
+   * @param commonServices  collection of all common service modules in the tree
    *
    * @throws AmbariException if resolution fails
    */
-  public void resolve(T parent, Map<String, StackModule> allStacks) throws AmbariException;
+  public void resolve(T parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) throws AmbariException;
 
   /**
    * Obtain the associated module information.
@@ -66,4 +67,14 @@ public interface StackDefinitionModule <T, I> {
    * Lifecycle even which is called when the associated stack has been fully resolved.
    */
   public void finalizeModule();
+
+  /**
+   * Module state.
+   * Initial state is INIT.
+   * When resolve is called state is set to VISITED.
+   * When resolve completes, state is set to RESOLVED.
+   *
+   * @return the module state
+   */
+  public ModuleState getModuleState();
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
index 2a14f51..62a1987 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
@@ -21,7 +21,9 @@ package org.apache.ambari.server.stack;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.stack.ServiceMetainfoXml;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -37,6 +39,20 @@ import java.util.Map;
  * stack information.
  */
 public class StackManager {
+
+  /**
+   * Delimiter used for parent path string
+   * Example:
+   *  HDP/2.0.6/HDFS
+   *  common-services/HDFS/2.1.0.2.0
+   */
+  public static String PATH_DELIMITER = "/";
+
+  /**
+   * Prefix used for common services parent path string
+   */
+  public static final String COMMON_SERVICES = "common-services";
+
   /**
    * Provides access to non-stack server functionality
    */
@@ -48,48 +64,32 @@ public class StackManager {
   private final static Logger LOG = LoggerFactory.getLogger(StackManager.class);
 
   /**
-   * Map of stack name to stack info
+   * Map of stack id to stack info
    */
   private Map<String, StackInfo> stackMap = new HashMap<String, StackInfo>();
 
-
   /**
    * Constructor.
+   * Initialize stack manager.
    *
-   * @param stackRoot     stack root directory
-   * @param stackContext  context which provides external functionality
+   * @param stackRoot           stack root directory
+   * @param commonServicesRoot  common services root directory
+   * @param stackContext        context which provides external functionality
    *
    * @throws AmbariException if an exception occurs while processing the stacks
    */
-  public StackManager(File stackRoot, StackContext stackContext) throws AmbariException {
+  public StackManager(File stackRoot, File commonServicesRoot, StackContext stackContext) throws AmbariException {
     validateStackDirectory(stackRoot);
+    validateCommonServicesDirectory(commonServicesRoot);
 
+    this.stackMap = new HashMap<String, StackInfo>();
     this.stackContext = stackContext;
-    Map<String, StackModule> stackModules = new HashMap<String, StackModule>();
-    File[] stackFiles = stackRoot.listFiles(AmbariMetaInfo.FILENAME_FILTER);
-    for (File stack : stackFiles) {
-      if (stack.isFile()) {
-        continue;
-      }
-      for (File stackFolder : stack.listFiles(AmbariMetaInfo.FILENAME_FILTER)) {
-        if (stackFolder.isFile()) {
-          continue;
-        }
-        String stackName = stackFolder.getParentFile().getName();
-        String stackVersion = stackFolder.getName();
 
-        StackModule stackModule = new StackModule(new StackDirectory(stackFolder.getPath()),stackContext);
-        stackModules.put(stackName + stackVersion, stackModule);
-        stackMap.put(stackName + stackVersion, stackModule.getModuleInfo());
-      }
-    }
-
-    if (stackMap.isEmpty()) {
-      throw new AmbariException("Unable to find stack definitions under " +
-          "stackRoot = " + stackRoot.getAbsolutePath());
-    }
+    Map<String, ServiceModule> commonServiceModules = parseCommonServicesDirectory(commonServicesRoot);
+    Map<String, StackModule> stackModules = parseStackDirectory(stackRoot);
 
-    fullyResolveStacks(stackModules);
+    fullyResolveCommonServices(stackModules, commonServiceModules);
+    fullyResolveStacks(stackModules, commonServiceModules);
   }
 
   /**
@@ -101,7 +101,7 @@ public class StackManager {
    *         If no matching stack exists, null is returned.
    */
   public StackInfo getStack(String name, String version) {
-    return stackMap.get(name + version);
+    return stackMap.get(name + StackManager.PATH_DELIMITER + version);
   }
 
   /**
@@ -142,13 +142,16 @@ public class StackManager {
   /**
    * Fully resolve all stacks.
    *
-   * @param stackModules  map of stack id which contains name and version to stack module.
+   * @param stackModules          map of stack id which contains name and version to stack module.
+   * @param commonServiceModules  map of common service id which contains name and version to stack module.
    * @throws AmbariException if unable to resolve all stacks
    */
-  private void fullyResolveStacks(Map<String, StackModule> stackModules) throws AmbariException {
+  private void fullyResolveStacks(
+      Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules)
+      throws AmbariException {
     for (StackModule stack : stackModules.values()) {
-      if (stack.getResolutionState() == StackModule.State.INIT) {
-        stack.resolve(null, stackModules);
+      if (stack.getModuleState() == ModuleState.INIT) {
+        stack.resolve(null, stackModules, commonServiceModules);
       }
     }
     // execute all of the repo tasks in a single thread executor
@@ -156,7 +159,46 @@ public class StackManager {
   }
 
   /**
+   * Fully resolve common services.
+   *
+   * @param stackModules          map of stack id which contains name and version to stack module.
+   * @param commonServiceModules  map of common service id which contains name and version to common service module.
+   * @throws AmbariException if unable to resolve all common services
+   */
+  private void fullyResolveCommonServices(
+      Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules)
+      throws AmbariException {
+    for(ServiceModule commonService : commonServiceModules.values()) {
+      if (commonService.getModuleState() == ModuleState.INIT) {
+        commonService.resolveCommonService(stackModules, commonServiceModules);
+      }
+    }
+  }
+
+  /**
+   * Validate that the specified common services root is a valid directory.
+   *
+   * @param commonServicesRoot the common services root directory to validate
+   * @throws AmbariException if the specified common services root directory is invalid
+   */
+  private void validateCommonServicesDirectory(File commonServicesRoot) throws AmbariException {
+    if(commonServicesRoot != null) {
+      String commonServicesRootAbsolutePath = commonServicesRoot.getAbsolutePath();
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Loading common services information"
+            + ", commonServicesRoot = " + commonServicesRootAbsolutePath);
+      }
+
+      if (!commonServicesRoot.isDirectory() && !commonServicesRoot.exists())
+        throw new AmbariException("" + Configuration.COMMON_SERVICES_DIR_PATH
+            + " should be a directory with common services"
+            + ", commonServicesRoot = " + commonServicesRootAbsolutePath);
+    }
+  }
+
+  /**
    * Validate that the specified stack root is a valid directory.
+   *
    * @param stackRoot  the stack root directory to validate
    * @throws AmbariException if the specified stack root directory is invalid
    */
@@ -172,4 +214,72 @@ public class StackManager {
           + " should be a directory with stack"
           + ", stackRoot = " + stackRootAbsPath);
   }
+
+  /**
+   * Parse the specified common services root directory
+   *
+   * @param commonServicesRoot  the common services root directory to parse
+   * @return map of common service id which contains name and version to common service module.
+   * @throws AmbariException if unable to parse all common services
+   */
+  private Map<String, ServiceModule> parseCommonServicesDirectory(File commonServicesRoot) throws AmbariException {
+    Map<String, ServiceModule> commonServiceModules = new HashMap<String, ServiceModule>();
+
+    if(commonServicesRoot != null) {
+      File[] commonServiceFiles = commonServicesRoot.listFiles(AmbariMetaInfo.FILENAME_FILTER);
+      for (File commonService : commonServiceFiles) {
+        if (commonService.isFile()) {
+          continue;
+        }
+        for (File serviceFolder : commonService.listFiles(AmbariMetaInfo.FILENAME_FILTER)) {
+          String serviceName = serviceFolder.getParentFile().getName();
+          String serviceVersion = serviceFolder.getName();
+          ServiceDirectory serviceDirectory = new ServiceDirectory(serviceFolder.getPath());
+          ServiceMetainfoXml metaInfoXml = serviceDirectory.getMetaInfoFile();
+          for (ServiceInfo serviceInfo : metaInfoXml.getServices()) {
+            ServiceModule serviceModule = new ServiceModule(stackContext, serviceInfo, serviceDirectory, true);
+            String commonServiceKey = serviceName + StackManager.PATH_DELIMITER + serviceVersion;
+            commonServiceModules.put(commonServiceKey, serviceModule);
+          }
+        }
+      }
+    }
+    return commonServiceModules;
+  }
+
+  /**
+   * Parse the specified stack root directory
+   *
+   * @param stackRoot  the stack root directory to parse
+   * @return map of stack id which contains name and version to stack module.
+   * @throws AmbariException if unable to parse all stacks
+   */
+  private Map<String, StackModule> parseStackDirectory(File stackRoot) throws AmbariException {
+    Map<String, StackModule> stackModules = new HashMap<String, StackModule>();
+
+    File[] stackFiles = stackRoot.listFiles(AmbariMetaInfo.FILENAME_FILTER);
+    for (File stack : stackFiles) {
+      if (stack.isFile()) {
+        continue;
+      }
+      for (File stackFolder : stack.listFiles(AmbariMetaInfo.FILENAME_FILTER)) {
+        if (stackFolder.isFile()) {
+          continue;
+        }
+        String stackName = stackFolder.getParentFile().getName();
+        String stackVersion = stackFolder.getName();
+
+        StackModule stackModule = new StackModule(new StackDirectory(stackFolder.getPath()), stackContext);
+        String stackKey = stackName + StackManager.PATH_DELIMITER + stackVersion;
+        stackModules.put(stackKey, stackModule);
+        stackMap.put(stackKey, stackModule.getModuleInfo());
+      }
+    }
+
+    if (stackMap.isEmpty()) {
+      throw new AmbariException("Unable to find stack definitions under " +
+          "stackRoot = " + stackRoot.getAbsolutePath());
+    }
+    return stackModules;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
index ea355c8..0fd8728 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
@@ -71,15 +71,6 @@ import java.util.Map;
  *
  */
 public class StackModule extends BaseModule<StackModule, StackInfo> {
-  /**
-   * Visitation state enum used for cycle detection
-   */
-  public enum State { INIT, VISITED, RESOLVED }
-
-  /**
-   * Visitation state of the stack
-   */
-  private State resolutionState = State.INIT;
 
   /**
    * Context which provides access to external functionality
@@ -136,23 +127,26 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
    * same stack hierarchy or may explicitly extend a service in a stack in a different
    * hierarchy.
    *
-   * @param parentModule  not used.  Each stack determines its own parent since stacks don't
-   *                      have containing modules
-   * @param allStacks     all stacks modules contained in the stack definition
+   * @param parentModule   not used.  Each stack determines its own parent since stacks don't
+   *                       have containing modules
+   * @param allStacks      all stacks modules contained in the stack definition
+   * @param commonServices all common services specified in the stack definition
    *
    * @throws AmbariException if an exception occurs during stack resolution
    */
   @Override
-  public void resolve(StackModule parentModule, Map<String, StackModule> allStacks) throws AmbariException {
-    resolutionState = State.VISITED;
+  public void resolve(
+      StackModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
+    moduleState = ModuleState.VISITED;
     String parentVersion = stackInfo.getParentStackVersion();
     // merge with parent version of same stack definition
     if (parentVersion != null) {
-      mergeStackWithParent(allStacks, parentVersion);
+      mergeStackWithParent(parentVersion, allStacks, commonServices);
     }
-    mergeServicesWithExplicitParent(allStacks);
+    mergeServicesWithExplicitParent(allStacks, commonServices);
     processRepositories();
-    resolutionState = State.RESOLVED;
+    moduleState = ModuleState.RESOLVED;
 
     finalizeModule();
   }
@@ -188,27 +182,19 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
   }
 
   /**
-   * Stack resolution state.
-   * Initial state is INIT.
-   * When resolve is called state is set to VISITED.
-   * When resolve completes, state is set to RESOLVED.
-   *
-   * @return the stacks resolution state
-   */
-  public State getResolutionState() {
-    return resolutionState;
-  }
-
-  /**
    * Merge the stack with its parent.
    *
    * @param allStacks      all stacks in stack definition
+   * @param commonServices all common services specified in the stack definition
    * @param parentVersion  version of the stacks parent
    *
    * @throws AmbariException if an exception occurs merging with the parent
    */
-  private void mergeStackWithParent(Map<String, StackModule> allStacks, String parentVersion) throws AmbariException {
-    String parentStackKey = stackInfo.getName() + parentVersion;
+  private void mergeStackWithParent(
+      String parentVersion, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
+
+    String parentStackKey = stackInfo.getName() + StackManager.PATH_DELIMITER + parentVersion;
     StackModule parentStack = allStacks.get(parentStackKey);
 
     if (parentStack == null) {
@@ -216,27 +202,31 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
           "' specifies a parent that doesn't exist");
     }
 
-    resolveStack(parentStack, allStacks);
-    mergeConfigurations(parentStack, allStacks);
+    resolveStack(parentStack, allStacks, commonServices);
+    mergeConfigurations(parentStack, allStacks, commonServices);
     mergeRoleCommandOrder(parentStack);
 
     if (stackInfo.getStackHooksFolder() == null) {
       stackInfo.setStackHooksFolder(parentStack.getModuleInfo().getStackHooksFolder());
     }
-    mergeServicesWithParent(allStacks, parentStack);
+    mergeServicesWithParent(parentStack, allStacks, commonServices);
   }
 
   /**
    * Merge child services with parent stack.
    *
-   * @param stacks       all stacks in stack definition
-   * @param parentStack  parent stack module
+   * @param parentStack    parent stack module
+   * @param allStacks      all stacks in stack definition
+   * @param commonServices all common services specified in the stack definition
    *
    * @throws AmbariException if an exception occurs merging the child services with the parent stack
    */
-  private void mergeServicesWithParent(Map<String, StackModule> stacks, StackModule parentStack) throws AmbariException {
+  private void mergeServicesWithParent(
+      StackModule parentStack, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
     stackInfo.getServices().clear();
-    Collection<ServiceModule> mergedModules = mergeChildModules(stacks, serviceModules, parentStack.serviceModules);
+    Collection<ServiceModule> mergedModules = mergeChildModules(
+        allStacks, commonServices, serviceModules, parentStack.serviceModules);
     for (ServiceModule module : mergedModules) {
       serviceModules.put(module.getId(), module);
       stackInfo.getServices().add(module.getModuleInfo());
@@ -245,52 +235,129 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
 
   /**
    * Merge services with their explicitly specified parent if one has been specified.
-   *
-   * @param stacks  all stacks specified in the stack definition
+   * @param allStacks      all stacks in stack definition
+   * @param commonServices all common services specified in the stack definition
    *
    * @throws AmbariException if an exception occurs while merging child services with their explicit parents
    */
-  private void mergeServicesWithExplicitParent(Map<String, StackModule> stacks) throws AmbariException {
+  private void mergeServicesWithExplicitParent(
+      Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) throws AmbariException {
     for (ServiceModule service : serviceModules.values()) {
       ServiceInfo serviceInfo = service.getModuleInfo();
       String parent = serviceInfo.getParent();
       if (parent != null) {
-        mergeServiceWithExplicitParent(stacks, service, parent);
+        mergeServiceWithExplicitParent(service, parent, allStacks, commonServices);
       }
     }
   }
 
   /**
    * Merge a service with its explicitly specified parent.
-   * @param stacks   all stacks specified in the stack definition
-   * @param service  the service to merge
-   * @param parent   the explicitly specified parent service
+   * @param service          the service to merge
+   * @param parent           the explicitly specified parent service
+   * @param allStacks        all stacks specified in the stack definition
+   * @param commonServices   all common services specified in the stack definition
    *
    * @throws AmbariException if an exception occurs merging a service with its explicit parent
    */
-  private void mergeServiceWithExplicitParent(Map<String, StackModule> stacks, ServiceModule service, String parent)
+  private void mergeServiceWithExplicitParent(
+      ServiceModule service, String parent, Map<String, StackModule> allStacks,
+      Map<String, ServiceModule> commonServices)
+      throws AmbariException {
+    if(isCommonServiceParent(parent)) {
+      mergeServiceWithCommonServiceParent(service, parent, allStacks,commonServices);
+    } else {
+      mergeServiceWithStackServiceParent(service, parent, allStacks, commonServices);
+    }
+  }
+
+  /**
+   * Check if parent is common service
+   * @param parent  Parent string
+   * @return true: if parent is common service, false otherwise
+   */
+  private boolean isCommonServiceParent(String parent) {
+    return parent != null
+        && !parent.isEmpty()
+        && parent.split(StackManager.PATH_DELIMITER)[0].equalsIgnoreCase(StackManager.COMMON_SERVICES);
+  }
+
+  /**
+   * Merge a service with its explicitly specified common service as parent.
+   * Parent: common-services/<serviceName>/<serviceVersion>
+   * Common Services Lookup Key: <serviceName>/<serviceVersion>
+   * Example:
+   *  Parent: common-services/HDFS/2.1.0.2.0
+   *  Key: HDFS/2.1.0.2.0
+   *
+   * @param service          the service to merge
+   * @param parent           the explicitly specified common service as parent
+   * @param allStacks        all stacks specified in the stack definition
+   * @param commonServices   all common services specified in the stack definition
+   * @throws AmbariException
+   */
+  private void mergeServiceWithCommonServiceParent(
+      ServiceModule service, String parent, Map<String, StackModule> allStacks,
+      Map<String, ServiceModule> commonServices)
       throws AmbariException {
+    ServiceInfo serviceInfo = service.getModuleInfo();
+    String[] parentToks = parent.split(StackManager.PATH_DELIMITER);
+    if(parentToks.length != 3 || !parentToks[0].equalsIgnoreCase(StackManager.COMMON_SERVICES)) {
+      throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+          + stackInfo.getVersion() + "' extends an invalid parent: '" + parent + "'");
+    }
+
+    String baseServiceKey = parentToks[1] + StackManager.PATH_DELIMITER + parentToks[2];
+    ServiceModule baseService = commonServices.get(baseServiceKey);
+    if (baseService == null) {
+      throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+          + stackInfo.getVersion() + "' extends a non-existent service: '" + parent + "'");
+    }
+    service.resolve(baseService, allStacks, commonServices);
+  }
 
+  /**
+   * Merge a service with its explicitly specified stack service as parent.
+   * Parent: <stackName>/<stackVersion>/<serviceName>
+   * Stack Lookup Key: <stackName>/<stackVersion>
+   * Example:
+   *  Parent: HDP/2.0.6/HDFS
+   *  Key: HDP/2.0.6
+   *
+   * @param service          the service to merge
+   * @param parent           the explicitly specified stack service as parent
+   * @param allStacks        all stacks specified in the stack definition
+   * @param commonServices   all common services specified in the stack definition
+   * @throws AmbariException
+   */
+  private void mergeServiceWithStackServiceParent(
+      ServiceModule service, String parent, Map<String, StackModule> allStacks,
+      Map<String, ServiceModule> commonServices)
+      throws AmbariException {
     ServiceInfo serviceInfo = service.getModuleInfo();
-    String[] parentToks = parent.split("/");
-    String baseStackKey = parentToks[0] + parentToks[1];
-    StackModule baseStack = stacks.get(baseStackKey);
+    String[] parentToks = parent.split(StackManager.PATH_DELIMITER);
+    if(parentToks.length != 3 || parentToks[0].equalsIgnoreCase(StackManager.COMMON_SERVICES)) {
+      throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+          + stackInfo.getVersion() + "' extends an invalid parent: '" + parent + "'");
+    }
+
+    String baseStackKey = parentToks[0] + StackManager.PATH_DELIMITER + parentToks[1];
+    StackModule baseStack = allStacks.get(baseStackKey);
     if (baseStack == null) {
       throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
           + stackInfo.getVersion() + "' extends a service in a non-existent stack: '" + baseStackKey + "'");
     }
 
-    resolveStack(baseStack, stacks);
+    resolveStack(baseStack, allStacks, commonServices);
 
     ServiceModule baseService = baseStack.serviceModules.get(parentToks[2]);
     if (baseService == null) {
       throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
           + stackInfo.getVersion() + "' extends a non-existent service: '" + parent + "'");
     }
-    service.resolve(baseService, stacks);
+    service.resolve(baseService, allStacks, commonServices);
   }
 
-
   /**
    * Populate the stack module and info from the stack definition.
    */
@@ -378,14 +445,17 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
    * Merge configurations with the parent configurations.
    *
    * @param parent  parent stack module
-   * @param stacks  all stack modules
+   * @param allStacks      all stacks in stack definition
+   * @param commonServices all common services specified in the stack definition
    */
-  private void mergeConfigurations(StackModule parent, Map<String, StackModule> stacks) throws AmbariException {
+  private void mergeConfigurations(
+      StackModule parent, Map<String,StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
     stackInfo.getProperties().clear();
     stackInfo.setAllConfigAttributes(new HashMap<String, Map<String, Map<String, String>>>());
 
     Collection<ConfigurationModule> mergedModules = mergeChildModules(
-        stacks, configurationModules, parent.configurationModules);
+        allStacks, commonServices, configurationModules, parent.configurationModules);
     for (ConfigurationModule module : mergedModules) {
       configurationModules.put(module.getId(), module);
       stackInfo.getProperties().addAll(module.getModuleInfo().getProperties());
@@ -397,13 +467,16 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
    * Resolve another stack module.
    *
    * @param stackToBeResolved  stack module to be resolved
-   * @param stacks             all stack modules in stack definition
+   * @param allStacks          all stack modules in stack definition
+   * @param commonServices     all common services specified in the stack definition
    * @throws AmbariException if unable to resolve the stack
    */
-  private void resolveStack(StackModule stackToBeResolved, Map<String, StackModule> stacks) throws AmbariException {
-    if (stackToBeResolved.getResolutionState() == State.INIT) {
-      stackToBeResolved.resolve(null, stacks);
-    } else if (stackToBeResolved.getResolutionState() == State.VISITED) {
+  private void resolveStack(
+      StackModule stackToBeResolved, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+      throws AmbariException {
+    if (stackToBeResolved.getModuleState() == ModuleState.INIT) {
+      stackToBeResolved.resolve(null, allStacks, commonServices);
+    } else if (stackToBeResolved.getModuleState() == ModuleState.VISITED) {
       //todo: provide more information to user about cycle
       throw new AmbariException("Cycle detected while parsing stack definition");
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
index 98d2645..734f4b9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
@@ -1735,7 +1735,7 @@ public class AmbariMetaInfoTest {
     OsFamily osFamily;
 
     public TestAmbariMetaInfo(File stackRoot, File serverVersionFile) throws Exception {
-      super(stackRoot, serverVersionFile);
+      super(stackRoot, null, serverVersionFile);
       // MetainfoDAO
       metaInfoDAO = createNiceMock(MetainfoDAO.class);
       Class<?> c = getClass().getSuperclass();

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/api/services/KerberosServiceMetaInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/KerberosServiceMetaInfoTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/KerberosServiceMetaInfoTest.java
index 7ecd833..538bbb5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/KerberosServiceMetaInfoTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/KerberosServiceMetaInfoTest.java
@@ -217,7 +217,7 @@ public class KerberosServiceMetaInfoTest {
     OsFamily osFamily;
 
     public TestAmbariMetaInfo(File stackRoot, File serverVersionFile) throws Exception {
-      super(stackRoot, serverVersionFile);
+      super(stackRoot, null, serverVersionFile);
       // MetainfoDAO
       metaInfoDAO = createNiceMock(MetainfoDAO.class);
       Class<?> c = getClass().getSuperclass();

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index 2a804e5..4db6738 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -8087,7 +8087,7 @@ public class AmbariManagementControllerTest {
     assertEquals(original, repo.getDefaultBaseUrl());
 
     // verify change with new meta info
-    AmbariMetaInfo ami = new AmbariMetaInfo(new File("src/test/resources/stacks"), new File("target/version"));
+    AmbariMetaInfo ami = new AmbariMetaInfo(new File("src/test/resources/stacks"), null, new File("target/version"));
     injector.injectMembers(ami);
     ami.init();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
index 8181cbc..42d6944 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
@@ -394,7 +394,7 @@ public class ComponentModuleTest {
     ComponentModule component = new ComponentModule(info);
     ComponentModule parentComponent = new ComponentModule(parentInfo);
 
-    component.resolve(parentComponent, Collections.<String, StackModule>emptyMap());
+    component.resolve(parentComponent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap());
 
     return component;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
index 5262c77..b6b7190 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
@@ -976,7 +976,7 @@ public class ServiceModuleTest {
   }
 
   private void resolveService(ServiceModule service, ServiceModule parent) throws AmbariException {
-    service.resolve(parent, Collections.<String, StackModule>emptyMap());
+    service.resolve(parent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap());
     // during runtime this would be called by the Stack module when it's resolve completed
     service.finalizeModule();
     parent.finalizeModule();

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
new file mode 100644
index 0000000..7b5168c
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
@@ -0,0 +1,167 @@
+/**
+ * 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.stack;
+
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.dao.MetainfoDAO;
+import org.apache.ambari.server.state.*;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.*;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * StackManager unit tests.
+ */
+public class StackManagerCommonServicesTest {
+
+  private static StackManager stackManager;
+  private static MetainfoDAO dao;
+  private static ActionMetadata actionMetadata;
+  private static OsFamily osFamily;
+
+  @BeforeClass
+  public static void initStack() throws Exception{
+    stackManager = createTestStackManager();
+  }
+
+  public static StackManager createTestStackManager() throws Exception {
+    String stack = ClassLoader.getSystemClassLoader().getResource("stacks_with_common_services").getPath();
+    String commonServices = ClassLoader.getSystemClassLoader().getResource("common-services").getPath();
+    return createTestStackManager(stack, commonServices);
+  }
+
+  public static StackManager createTestStackManager(String stackRoot, String commonServicesRoot) throws Exception {
+    try {
+      //todo: dao , actionMetaData expectations
+      dao = createNiceMock(MetainfoDAO.class);
+      actionMetadata = createNiceMock(ActionMetadata.class);
+      Configuration config = createNiceMock(Configuration.class);
+      expect(config.getSharedResourcesDirPath()).andReturn(
+          ClassLoader.getSystemClassLoader().getResource("").getPath()).anyTimes();
+      replay(config);
+      osFamily = new OsFamily(config);
+
+      replay(dao, actionMetadata);
+      StackManager stackManager = new StackManager(
+          new File(stackRoot), new File(commonServicesRoot), new StackContext(dao, actionMetadata, osFamily));
+      return stackManager;
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testGetStacks_count() throws Exception {
+    Collection<StackInfo> stacks = stackManager.getStacks();
+    assertEquals(2, stacks.size());
+  }
+
+  @Test
+  public void testGetStack_name__count() {
+    Collection<StackInfo> stacks = stackManager.getStacks("HDP");
+    assertEquals(2, stacks.size());
+  }
+
+  @Test
+  public void testGetStack_basic() {
+    StackInfo stack = stackManager.getStack("HDP", "0.1");
+    assertNotNull(stack);
+    assertEquals("HDP", stack.getName());
+    assertEquals("0.1", stack.getVersion());
+
+
+    Collection<ServiceInfo> services = stack.getServices();
+    assertEquals(3, services.size());
+
+    Map<String, ServiceInfo> serviceMap = new HashMap<String, ServiceInfo>();
+    for (ServiceInfo service : services) {
+      serviceMap.put(service.getName(), service);
+    }
+    ServiceInfo hdfsService = serviceMap.get("HDFS");
+    assertNotNull(hdfsService);
+    List<ComponentInfo> components = hdfsService.getComponents();
+    assertEquals(6, components.size());
+    List<PropertyInfo> properties = hdfsService.getProperties();
+    assertEquals(62, properties.size());
+
+    // test a couple of the properties for filename
+    boolean hdfsPropFound = false;
+    boolean hbasePropFound = false;
+    for (PropertyInfo p : properties) {
+      if (p.getName().equals("hbase.regionserver.msginterval")) {
+        assertEquals("hbase-site.xml", p.getFilename());
+        hbasePropFound = true;
+      } else if (p.getName().equals("dfs.name.dir")) {
+        assertEquals("hdfs-site.xml", p.getFilename());
+        hdfsPropFound = true;
+      }
+    }
+    assertTrue(hbasePropFound);
+    assertTrue(hdfsPropFound);
+
+    ServiceInfo mrService = serviceMap.get("MAPREDUCE");
+    assertNotNull(mrService);
+    components = mrService.getComponents();
+    assertEquals(3, components.size());
+
+    ServiceInfo pigService = serviceMap.get("PIG");
+    assertNotNull(pigService);
+    assertEquals("PIG", pigService.getName());
+    assertEquals("1.0", pigService.getVersion());
+    assertEquals("This is comment for PIG service", pigService.getComment());
+    components = pigService.getComponents();
+    assertEquals(1, components.size());
+    CommandScriptDefinition commandScript = pigService.getCommandScript();
+    assertEquals("scripts/service_check.py", commandScript.getScript());
+    assertEquals(CommandScriptDefinition.Type.PYTHON, commandScript.getScriptType());
+    assertEquals(300, commandScript.getTimeout());
+    List<String> configDependencies = pigService.getConfigDependencies();
+    assertEquals(1, configDependencies.size());
+    assertEquals("global", configDependencies.get(0));
+    assertEquals("global", pigService.getConfigDependenciesWithComponents().get(0));
+    ComponentInfo client = pigService.getClientComponent();
+    assertNotNull(client);
+    assertEquals("PIG", client.getName());
+    assertEquals("0+", client.getCardinality());
+    assertEquals("CLIENT", client.getCategory());
+    assertEquals("configuration", pigService.getConfigDir());
+    assertEquals("2.0", pigService.getSchemaVersion());
+    Map<String, ServiceOsSpecific> osInfoMap = pigService.getOsSpecifics();
+    assertEquals(1, osInfoMap.size());
+    ServiceOsSpecific osSpecific = osInfoMap.get("centos6");
+    assertNotNull(osSpecific);
+    assertEquals("centos6", osSpecific.getOsFamily());
+    assertNull(osSpecific.getRepo());
+    List<ServiceOsSpecific.Package> packages = osSpecific.getPackages();
+    assertEquals(1, packages.size());
+    ServiceOsSpecific.Package pkg = packages.get(0);
+    assertEquals("pig", pkg.getName());
+
+    assertEquals(pigService.getParent(), "common-services/PIG/1.0");
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
new file mode 100644
index 0000000..26d7826
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
@@ -0,0 +1,91 @@
+/**
+ * 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.stack;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.dao.MetainfoDAO;
+import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Collection;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * StackManager Misc unit tests.
+ */
+public class StackManagerMiscTest  {
+
+  @Test
+  public void testCycleDetection() throws Exception {
+    MetainfoDAO dao = createNiceMock(MetainfoDAO.class);
+    ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
+    OsFamily osFamily = createNiceMock(OsFamily.class);
+    replay(actionMetadata);
+    try {
+      String stacksCycle1 = ClassLoader.getSystemClassLoader().getResource("stacks_with_cycle").getPath();
+      StackManager stackManager = new StackManager(new File(stacksCycle1), null,
+          new StackContext(dao, actionMetadata, osFamily));
+      fail("Expected exception due to cyclic stack");
+    } catch (AmbariException e) {
+      // expected
+      assertEquals("Cycle detected while parsing stack definition", e.getMessage());
+    }
+    try {
+      String stacksCycle2 = ClassLoader.getSystemClassLoader().getResource("stacks_with_cycle2").getPath();
+      StackManager stackManager = new StackManager(new File(stacksCycle2), null,
+          new StackContext(dao, actionMetadata, osFamily));
+      fail("Expected exception due to cyclic stack");
+    } catch (AmbariException e) {
+      // expected
+      assertEquals("Cycle detected while parsing stack definition", e.getMessage());
+    }
+  }
+
+  /**
+   * This test ensures the service status check is added into the action metadata when
+   * the stack has no parent and is the only stack in the stack family
+   */
+  @Test
+  public void testGetServiceInfoFromSingleStack() throws Exception {
+    MetainfoDAO dao = createNiceMock(MetainfoDAO.class);
+    ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
+    OsFamily  osFamily = createNiceMock(OsFamily.class);
+
+    // ensure that service check is added for HDFS
+    actionMetadata.addServiceCheckAction("HDFS");
+    replay(dao, actionMetadata, osFamily);
+    String singleStack = ClassLoader.getSystemClassLoader().getResource("single_stack").getPath();
+
+    StackManager stackManager = new StackManager(
+        new File(singleStack.replace(StackManager.PATH_DELIMITER, File.separator)),
+        null,
+        new StackContext(dao, actionMetadata, osFamily));
+
+    Collection<StackInfo> stacks = stackManager.getStacks();
+    assertEquals(1, stacks.size());
+    assertNotNull(stacks.iterator().next().getService("HDFS"));
+
+    verify(dao, actionMetadata, osFamily);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerTest.java
index 9d75643..f5c2938 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerTest.java
@@ -63,10 +63,7 @@ public class StackManagerTest {
   }
 
   public static StackManager createTestStackManager() throws Exception {
-    String stack = "./src/test/resources/stacks/";
-    if (System.getProperty("os.name").contains("Windows")) {
-      stack = ClassLoader.getSystemClassLoader().getResource("stacks").getPath();
-    }
+    String stack = ClassLoader.getSystemClassLoader().getResource("stacks").getPath();
     return createTestStackManager(stack);
   }
 
@@ -76,17 +73,15 @@ public class StackManagerTest {
       dao = createNiceMock(MetainfoDAO.class);
       actionMetadata = createNiceMock(ActionMetadata.class);
       Configuration config = createNiceMock(Configuration.class);
-      if (System.getProperty("os.name").contains("Windows")) {
-        expect(config.getSharedResourcesDirPath()).andReturn(ClassLoader.getSystemClassLoader().getResource("").getPath()).anyTimes();
-      }
-      else {
-        expect(config.getSharedResourcesDirPath()).andReturn("./src/test/resources").anyTimes();
-      }
+      expect(config.getSharedResourcesDirPath()).andReturn(
+          ClassLoader.getSystemClassLoader().getResource("").getPath()).anyTimes();
       replay(config);
       osFamily = new OsFamily(config);
 
       replay(dao, actionMetadata);
-      return new StackManager(new File(stackRoot), new StackContext(dao, actionMetadata, osFamily));
+      StackManager stackManager = new StackManager(
+          new File(stackRoot), null, new StackContext(dao, actionMetadata, osFamily));
+      return stackManager;
     } catch (Exception e) {
       e.printStackTrace();
       throw e;
@@ -154,7 +149,6 @@ public class StackManagerTest {
     assertNotNull(pigService);
     assertEquals("PIG", pigService.getName());
     assertEquals("1.0", pigService.getVersion());
-    assertNull(pigService.getParent());
     assertEquals("This is comment for PIG service", pigService.getComment());
     components = pigService.getComponents();
     assertEquals(1, components.size());
@@ -183,6 +177,8 @@ public class StackManagerTest {
     assertEquals(1, packages.size());
     ServiceOsSpecific.Package pkg = packages.get(0);
     assertEquals("pig", pkg.getName());
+
+    assertNull(pigService.getParent());
   }
 
   @Test
@@ -519,38 +515,6 @@ public class StackManagerTest {
   }
 
   @Test
-  public void testCycleDetection() throws Exception {
-    ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
-    OsFamily osFamily = createNiceMock(OsFamily.class);
-    replay(actionMetadata);
-    try {
-      String stacksCycle1 = "./src/test/resources/stacks_with_cycle/";
-      if (System.getProperty("os.name").contains("Windows")) {
-        stacksCycle1 = ClassLoader.getSystemClassLoader().getResource("stacks_with_cycle").getPath();
-      }
-      new StackManager(new File(stacksCycle1),
-              new StackContext(null, actionMetadata, osFamily));
-      fail("Expected exception due to cyclic stack");
-    } catch (AmbariException e) {
-      // expected
-      assertEquals("Cycle detected while parsing stack definition", e.getMessage());
-    }
-
-    try {
-      String stacksCycle2 = "./src/test/resources/stacks_with_cycle2/";
-      if (System.getProperty("os.name").contains("Windows")) {
-        stacksCycle2 = ClassLoader.getSystemClassLoader().getResource("stacks_with_cycle2").getPath();
-      }
-      new StackManager(new File(stacksCycle2),
-              new StackContext(null, actionMetadata, osFamily));
-      fail("Expected exception due to cyclic stack");
-    } catch (AmbariException e) {
-      // expected
-      assertEquals("Cycle detected while parsing stack definition", e.getMessage());
-    }
-  }
-
-  @Test
   public void testExcludedConfigTypes() {
     StackInfo stack = stackManager.getStack("HDP", "2.0.8");
     ServiceInfo service = stack.getService("HBASE");
@@ -589,34 +553,6 @@ public class StackManagerTest {
     assertNotNull(hdfsService.getMetricsFile());
   }
 
-  /**
-   * This test ensures the service status check is added into the action metadata when
-   * the stack has no parent and is the only stack in the stack family
-   */
-  @Test
-  public void testGetServiceInfoFromSingleStack() throws Exception {
-    dao = createNiceMock(MetainfoDAO.class);
-    actionMetadata = createNiceMock(ActionMetadata.class);
-    osFamily = createNiceMock(OsFamily.class);
-
-    // ensure that service check is added for HDFS
-    actionMetadata.addServiceCheckAction("HDFS");
-    replay(dao, actionMetadata, osFamily);
-    String singleStack = "./src/test/resources/single_stack";
-    if (System.getProperty("os.name").contains("Windows")) {
-      singleStack = ClassLoader.getSystemClassLoader().getResource("single_stack").getPath();
-    }
-    StackManager stackManager = new StackManager(
-        new File(singleStack.replace("/", File.separator)),
-        new StackContext(dao, actionMetadata, osFamily));
-
-    Collection<StackInfo> stacks = stackManager.getStacks();
-    assertEquals(1, stacks.size());
-    assertNotNull(stacks.iterator().next().getService("HDFS"));
-
-    verify(dao, actionMetadata, osFamily);
-  }
-
   @Test
   public void testMergeRoleCommandOrder() throws Exception {
     StackInfo stack = stackManager.getStack("HDP", "2.1.1");

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/resources/common-services/HBASE/1.0/configuration/hbase-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/common-services/HBASE/1.0/configuration/hbase-site.xml b/ambari-server/src/test/resources/common-services/HBASE/1.0/configuration/hbase-site.xml
new file mode 100644
index 0000000..5024e85
--- /dev/null
+++ b/ambari-server/src/test/resources/common-services/HBASE/1.0/configuration/hbase-site.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+/**
+ * Copyright 2007 The Apache Software Foundation
+ *
+ * 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.
+ */
+-->
+<configuration>
+  <property>
+    <name>hbase.regionserver.msginterval</name>
+    <value>1000</value>
+    <description>Interval between messages from the RegionServer to HMaster
+    in milliseconds.  Default is 15. Set this value low if you want unit
+    tests to be responsive.
+    </description>
+  </property>
+  <property>
+    <name>hbase.client.pause</name>
+    <value>5000</value>
+    <description>General client pause value.  Used mostly as value to wait
+    before running a retry of a failed get, region lookup, etc.</description>
+  </property>
+  <property>
+    <name>hbase.master.meta.thread.rescanfrequency</name>
+    <value>10000</value>
+    <description>How long the HMaster sleeps (in milliseconds) between scans of
+    the root and meta tables.
+    </description>
+  </property>
+  <property>
+    <name>hbase.server.thread.wakefrequency</name>
+    <value>1000</value>
+    <description>Time to sleep in between searches for work (in milliseconds).
+    Used as sleep interval by service threads such as META scanner and log roller.
+    </description>
+  </property>
+  <property>
+    <name>hbase.regionserver.handler.count</name>
+    <value>5</value>
+    <description>Count of RPC Server instances spun up on RegionServers
+    Same property is used by the HMaster for count of master handlers.
+    Default is 10.
+    </description>
+  </property>
+  <property>
+    <name>hbase.master.lease.period</name>
+    <value>6000</value>
+    <description>Length of time the master will wait before timing out a region
+    server lease. Since region servers report in every second (see above), this
+    value has been reduced so that the master will notice a dead region server
+    sooner. The default is 30 seconds.
+    </description>
+  </property>
+  <property>
+    <name>hbase.master.info.port</name>
+    <value>-1</value>
+    <description>The port for the hbase master web UI
+    Set to -1 if you do not want the info server to run.
+    </description>
+  </property>
+  <property>
+    <name>hbase.regionserver.info.port</name>
+    <value>-1</value>
+    <description>The port for the hbase regionserver web UI
+    Set to -1 if you do not want the info server to run.
+    </description>
+  </property>
+  <property>
+    <name>hbase.regionserver.info.port.auto</name>
+    <value>true</value>
+    <description>Info server auto port bind. Enables automatic port
+    search if hbase.regionserver.info.port is already in use.
+    Enabled for testing to run multiple tests on one machine.
+    </description>
+  </property>
+  <property>
+    <name>hbase.master.lease.thread.wakefrequency</name>
+    <value>3000</value>
+    <description>The interval between checks for expired region server leases.
+    This value has been reduced due to the other reduced values above so that
+    the master will notice a dead region server sooner. The default is 15 seconds.
+    </description>
+  </property>
+  <property>
+    <name>hbase.regionserver.optionalcacheflushinterval</name>
+    <value>10000</value>
+    <description>
+    Amount of time to wait since the last time a region was flushed before
+    invoking an optional cache flush. Default 60,000.
+    </description>
+  </property>
+  <property>
+    <name>hbase.regionserver.safemode</name>
+    <value>false</value>
+    <description>
+    Turn on/off safe mode in region server. Always on for production, always off
+    for tests.
+    </description>
+  </property>
+  <property>
+    <name>hbase.hregion.max.filesize</name>
+    <value>67108864</value>
+    <description>
+    Maximum desired file size for an HRegion.  If filesize exceeds
+    value + (value / 2), the HRegion is split in two.  Default: 256M.
+
+    Keep the maximum filesize small so we split more often in tests.
+    </description>
+  </property>
+  <property>
+    <name>hadoop.log.dir</name>
+    <value>${user.dir}/../logs</value>
+  </property>
+  <property>
+    <name>hbase.zookeeper.property.clientPort</name>
+    <value>21818</value>
+    <description>Property from ZooKeeper's config zoo.cfg.
+    The port at which the clients will connect.
+    </description>
+  </property>
+</configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/14c86996/ambari-server/src/test/resources/common-services/HBASE/1.0/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/common-services/HBASE/1.0/metainfo.xml b/ambari-server/src/test/resources/common-services/HBASE/1.0/metainfo.xml
new file mode 100644
index 0000000..9646d63
--- /dev/null
+++ b/ambari-server/src/test/resources/common-services/HBASE/1.0/metainfo.xml
@@ -0,0 +1,121 @@
+<?xml version="1.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.
+-->
+<metainfo>
+  <schemaVersion>2.0</schemaVersion>
+  <services>
+    <service>
+      <name>HBASE</name>
+      <comment>This is comment for HBASE service</comment>
+      <version>1.0</version>
+
+      <components>
+        <component>
+          <name>HBASE_MASTER</name>
+          <category>MASTER</category>
+          <cardinality>1</cardinality>
+          <dependencies>
+            <dependency>
+              <name>HDFS/HDFS_CLIENT</name>
+              <scope>host</scope>
+              <auto-deploy>
+                <enabled>true</enabled>
+              </auto-deploy>
+            </dependency>
+            <dependency>
+              <name>ZOOKEEPER/ZOOKEEPER_SERVER</name>
+              <scope>cluster</scope>
+              <auto-deploy>
+                <enabled>true</enabled>
+                <co-locate>HBASE/HBASE_MASTER</co-locate>
+              </auto-deploy>
+            </dependency>
+          </dependencies>
+          <commandScript>
+            <script>scripts/hbase_master.py</script>
+            <scriptType>PYTHON</scriptType>
+            <timeout>600</timeout>
+          </commandScript>
+          <customCommands>
+            <customCommand>
+              <name>DECOMMISSION</name>
+              <commandScript>
+                <script>scripts/hbase_master.py</script>
+                <scriptType>PYTHON</scriptType>
+                <timeout>600</timeout>
+              </commandScript>
+            </customCommand>
+          </customCommands>
+        </component>
+
+        <component>
+          <name>HBASE_REGIONSERVER</name>
+          <category>SLAVE</category>
+          <cardinality>1+</cardinality>
+          <commandScript>
+            <script>scripts/hbase_regionserver.py</script>
+            <scriptType>PYTHON</scriptType>
+          </commandScript>
+          <customCommands>
+            <customCommand>
+              <name>DECOMMISSION</name>
+              <commandScript>
+                <script>scripts/hbase_regionserver.py</script>
+                <scriptType>PYTHON</scriptType>
+                <timeout>600</timeout>
+              </commandScript>
+            </customCommand>
+          </customCommands>
+        </component>
+
+        <component>
+          <name>HBASE_CLIENT</name>
+          <category>CLIENT</category>
+          <cardinality>0+</cardinality>
+          <commandScript>
+            <script>scripts/hbase_client.py</script>
+            <scriptType>PYTHON</scriptType>
+          </commandScript>
+        </component>
+      </components>
+
+      <osSpecifics>
+        <osSpecific>
+          <osFamily>centos6</osFamily>
+          <packages>
+            <package>
+              <name>hbase</name>
+            </package>
+          </packages>
+        </osSpecific>
+      </osSpecifics>
+
+      <commandScript>
+        <script>scripts/service_check.py</script>
+        <scriptType>PYTHON</scriptType>
+        <timeout>300</timeout>
+      </commandScript>
+
+      <configuration-dependencies>
+        <config-type>global</config-type>
+        <config-type>hbase-policy</config-type>
+        <config-type>hbase-site</config-type>
+      </configuration-dependencies>
+
+    </service>
+  </services>
+</metainfo>