ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dmitriu...@apache.org
Subject [2/2] ambari git commit: AMBARI-9766. Exception during stack loading fails entire load process (dlysnichenko)
Date Tue, 24 Feb 2015 11:59:19 GMT
AMBARI-9766. Exception during stack loading fails entire load process (dlysnichenko)


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

Branch: refs/heads/branch-2.0.0
Commit: a3e1edb33408692c712c05aeb83fb6e8562b9c89
Parents: d799c35
Author: Lisnichenko Dmitro <dlysnichenko@hortonworks.com>
Authored: Tue Feb 24 13:58:48 2015 +0200
Committer: Lisnichenko Dmitro <dlysnichenko@hortonworks.com>
Committed: Tue Feb 24 13:58:48 2015 +0200

----------------------------------------------------------------------
 .../server/controller/StackVersionResponse.java |  36 +++++-
 .../internal/StackVersionResourceProvider.java  |   8 ++
 .../ambari/server/stack/ComponentModule.java    |  44 +++++++-
 .../server/stack/ConfigurationDirectory.java    |  24 +++-
 .../ambari/server/stack/ConfigurationInfo.java  |  35 +++++-
 .../server/stack/ConfigurationModule.java       |  50 ++++++++-
 .../ambari/server/stack/ServiceDirectory.java   |   5 +-
 .../ambari/server/stack/ServiceModule.java      |  43 ++++++-
 .../server/stack/StackDefinitionModule.java     |  12 ++
 .../ambari/server/stack/StackDirectory.java     |  14 ++-
 .../ambari/server/stack/StackManager.java       |  19 +++-
 .../apache/ambari/server/stack/StackModule.java | 112 +++++++++++++++++--
 .../apache/ambari/server/stack/Validable.java   |  48 ++++++++
 .../apache/ambari/server/state/ServiceInfo.java |  41 ++++++-
 .../apache/ambari/server/state/StackInfo.java   |  45 +++++++-
 .../server/state/stack/ConfigurationXml.java    |  46 +++++++-
 .../server/state/stack/RepositoryXml.java       |  46 +++++++-
 .../server/state/stack/ServiceMetainfoXml.java  |  50 ++++++++-
 .../server/state/stack/StackMetainfoXml.java    |  46 +++++++-
 .../src/main/resources/properties.json          |   2 +
 .../server/api/services/AmbariMetaInfoTest.java |  13 +--
 21 files changed, 692 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/controller/StackVersionResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackVersionResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackVersionResponse.java
index a8ab755..005b8a1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackVersionResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackVersionResponse.java
@@ -21,16 +21,19 @@ package org.apache.ambari.server.controller;
 import java.io.File;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import org.apache.ambari.server.stack.Validable;
 
 
-public class StackVersionResponse {
+public class StackVersionResponse implements Validable{
 
   private String stackName;
   private String stackVersion;
   private String minUpgradeVersion;
   private boolean active;
+  private boolean valid;
   private String parentVersion;
   private Map<String, Map<String, Map<String, String>>> configTypes;
 
@@ -54,7 +57,7 @@ public class StackVersionResponse {
                               Map<String, Map<String, Map<String, String>>> configTypes,
                               File stackKerberosDescriptorFile,
                               Collection<File> serviceKerberosDescriptorFiles,
-                              Set<String> upgradePacks) {
+                              Set<String> upgradePacks, boolean valid, Collection errorSet) {
     setStackVersion(stackVersion);
     setMinUpgradeVersion(minUpgradeVersion);
     setActive(active);
@@ -63,8 +66,37 @@ public class StackVersionResponse {
     setKerberosDescriptorFile(stackKerberosDescriptorFile);
     setServiceKerberosDescriptorFiles(serviceKerberosDescriptorFiles);
     setUpgradePacks(upgradePacks);
+    setValid(valid);
+    setErrors(errorSet);
   }
 
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }  
+
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
+  
   public String getStackName() {
     return stackName;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
index ddb9301..ca66819 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
@@ -55,6 +55,8 @@ public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
   public static final String STACK_NAME_PROPERTY_ID        = PropertyHelper.getPropertyId("Versions", "stack_name");
   public static final String STACK_MIN_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Versions", "min_upgrade_version");
   public static final String STACK_ACTIVE_PROPERTY_ID      = PropertyHelper.getPropertyId("Versions", "active");
+  public static final String STACK_VALID_PROPERTY_ID      = PropertyHelper.getPropertyId("Versions", "valid");
+  public static final String STACK_ERROR_SET      = PropertyHelper.getPropertyId("Versions", "stack-errors");
   public static final String STACK_CONFIG_TYPES            = PropertyHelper.getPropertyId("Versions", "config_types");
   public static final String STACK_PARENT_PROPERTY_ID      = PropertyHelper.getPropertyId("Versions", "parent_stack_version");
   public static final String KERBEROS_DESCRIPTOR_PROPERTY_ID = PropertyHelper.getPropertyId("Versions", "kerberos_descriptor");
@@ -122,6 +124,12 @@ public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
       setResourceProperty(resource, STACK_ACTIVE_PROPERTY_ID,
           response.isActive(), requestedIds);
 
+      setResourceProperty(resource, STACK_VALID_PROPERTY_ID,
+          response.isValid(), requestedIds);
+      
+      setResourceProperty(resource, STACK_ERROR_SET,
+          response.getErrors(), requestedIds);
+      
       setResourceProperty(resource, STACK_PARENT_PROPERTY_ID,
         response.getParentVersion(), requestedIds);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 4205da8..c86073f 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
@@ -26,17 +26,24 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Component module which provides all functionality related to parsing and fully
  * resolving service components from the stack definition.
  */
-public class ComponentModule extends BaseModule<ComponentModule, ComponentInfo> {
+public class ComponentModule extends BaseModule<ComponentModule, ComponentInfo> implements Validable {
   /**
    * Corresponding component info
    */
   private ComponentInfo componentInfo;
+  
+  /**
+   * validity flag
+   */
+  protected boolean valid = true;
 
+          
   /**
    * Constructor.
    *
@@ -49,7 +56,13 @@ public class ComponentModule extends BaseModule<ComponentModule, ComponentInfo>
   @Override
   public void resolve(ComponentModule parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) {
     ComponentInfo parentInfo = parent.getModuleInfo();
-
+    if (parent != null){
+      if (!parent.isValid()){
+        setValid(false);
+        setErrors(parent.getErrors());
+      }
+    }
+    
     if (componentInfo.getCommandScript() == null) {
       componentInfo.setCommandScript(parentInfo.getCommandScript());
     }
@@ -148,4 +161,31 @@ public class ComponentModule extends BaseModule<ComponentModule, ComponentInfo>
       }
     }
   }
+
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }
+  
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationDirectory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationDirectory.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationDirectory.java
index d4c99e5..7f21aaa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationDirectory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationDirectory.java
@@ -32,6 +32,9 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.UnmarshalException;
+import org.xml.sax.SAXParseException;
 
 /**
  * Encapsulates IO operations on a stack definition configuration directory.
@@ -81,15 +84,30 @@ public class ConfigurationDirectory extends StackDefinitionDirectory {
     if (configFiles != null) {
       for (File configFile : configFiles) {
         if (configFile.getName().endsWith(AmbariMetaInfo.SERVICE_CONFIG_FILE_NAME_POSTFIX)) {
+          String configType = ConfigHelper.fileNameToConfigType(configFile.getName());
+          ConfigurationXml config = null;
           try {
-            String configType = ConfigHelper.fileNameToConfigType(configFile.getName());
-            ConfigurationXml config = unmarshaller.unmarshal(ConfigurationXml.class, configFile);
+            config = unmarshaller.unmarshal(ConfigurationXml.class, configFile);
             ConfigurationInfo configInfo = new ConfigurationInfo(parseProperties(config,
                 configFile.getName()), parseAttributes(config));
             ConfigurationModule module = new ConfigurationModule(configType, configInfo);
             configurationModules.put(configType, module);
           } catch (Exception e) {
-            LOG.error("Could not load configuration for " + configFile, e);
+            String error = null;
+            if (e instanceof JAXBException || e instanceof UnmarshalException || e instanceof SAXParseException) {
+              error = "Could not parse XML " + configFile + ": " + e;
+            } else {
+              error = "Could not load configuration for " + configFile;
+            }
+            config = new ConfigurationXml();
+            config.setValid(false);
+            config.setErrors(error);
+            ConfigurationInfo configInfo = new ConfigurationInfo(parseProperties(config,
+                configFile.getName()), parseAttributes(config));
+            configInfo.setValid(false);
+            configInfo.setErrors(error);
+            ConfigurationModule module = new ConfigurationModule(configType, configInfo);
+            configurationModules.put(configType, module);
           }
         }
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationInfo.java
index 97d57cb..d00b135 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ConfigurationInfo.java
@@ -20,7 +20,9 @@ package org.apache.ambari.server.stack;
 
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.ambari.server.state.PropertyInfo;
 import org.slf4j.Logger;
@@ -30,7 +32,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Encapsulates configuration properties and attributes for a single type.
  */
-public class ConfigurationInfo {
+public class ConfigurationInfo implements Validable{
   /**
    * Collection of properties
    */
@@ -47,6 +49,11 @@ public class ConfigurationInfo {
   private final static Logger LOG = LoggerFactory.getLogger(ConfigurationInfo.class);
 
   /**
+   * validity flag
+   */
+  protected boolean valid = true;
+  
+  /**
    * Constructor.
    *
    * @param properties  configuration properties
@@ -112,7 +119,33 @@ public class ConfigurationInfo {
     this.attributes = attributes;
   }
 
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
 
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
+  
   /**
    * Service configuration-types can support different abilities. This
    * enumerates the various abilities that configuration-types can support.

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 fde7b2d..90e7ed3 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
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 
 /**
@@ -32,7 +33,7 @@ import java.util.Map;
  * resolving a configuration from the stack definition. Each instance is specific
  * to a configuration type.
  */
-public class ConfigurationModule extends BaseModule<ConfigurationModule, ConfigurationInfo> {
+public class ConfigurationModule extends BaseModule<ConfigurationModule, ConfigurationInfo> implements Validable{
   /**
    * Configuration type
    */
@@ -48,7 +49,23 @@ public class ConfigurationModule extends BaseModule<ConfigurationModule, Configu
    */
   private boolean isDeleted;
 
+  /**
+   * validity flag
+   */
+  protected boolean valid = true;
+
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
 
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+  
   /**
    * Constructor.
    *
@@ -58,11 +75,27 @@ public class ConfigurationModule extends BaseModule<ConfigurationModule, Configu
   public ConfigurationModule(String configType, ConfigurationInfo info) {
     this.configType = configType;
     this.info = info;
+    if (info != null && !info.isValid()){
+      setValid(info.isValid());
+      setErrors(info.getErrors());
+    }
   }
 
   @Override
   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
+   
+    if (parent != null && parent.info != null){
+      if (!parent.isValid() || !parent.info.isValid()){
+        setValid(false);
+        info.setValid(false);
+        setErrors(parent.getErrors());
+        setErrors(parent.info.getErrors());
+        info.setErrors(parent.getErrors());
+        info.setErrors(parent.info.getErrors());
+      }
+    }
+    
     mergeProperties(parent);
 
     if (isExtensionEnabled()) {
@@ -167,4 +200,19 @@ public class ConfigurationModule extends BaseModule<ConfigurationModule, Configu
     String val = supportsMap.get(ConfigurationInfo.Supports.DO_NOT_EXTEND.getPropertyName());
     return val == null || val.equals("false");
   }
+
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
index c502244..9b32a97 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
@@ -172,7 +172,10 @@ public abstract class ServiceDirectory extends StackDefinitionDirectory {
     try {
       metaInfoXml = unmarshaller.unmarshal(ServiceMetainfoXml.class, f);
     } catch (JAXBException e) {
-      throw new AmbariException(String.format("Unable to parse service metainfo.xml file '%s' ", f.getAbsolutePath()), e);
+      metaInfoXml = new ServiceMetainfoXml();
+      metaInfoXml.setValid(false);
+      metaInfoXml.setErrors(String.format("Unable to parse service metainfo.xml file '%s' ", f.getAbsolutePath()));
+      metaInfoXml.setSchemaVersion(getAbsolutePath().replace(f.getParentFile().getParentFile().getParent()+File.separator, ""));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 a30d761..8b94101 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
@@ -37,7 +37,7 @@ import org.apache.ambari.server.state.ServiceInfo;
  * Service module which provides all functionality related to parsing and fully
  * resolving services from the stack definition.
  */
-public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
+public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implements Validable{
   /**
    * Corresponding service info
    */
@@ -71,6 +71,11 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
   private boolean isCommonService;
 
   /**
+   * validity flag
+   */
+  protected boolean valid = true;  
+  
+  /**
    * Constructor.
    *
    * @param stackContext      stack context which provides module access to external functionality
@@ -116,7 +121,7 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
       ServiceModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
       throws AmbariException {
     ServiceInfo parent = parentModule.getModuleInfo();
-
+    
     if (serviceInfo.getComment() == null) {
       serviceInfo.setComment(parent.getComment());
     }
@@ -243,6 +248,13 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
     if (configDirectory != null) {
       for (ConfigurationModule config : configDirectory.getConfigurationModules()) {
           ConfigurationInfo info = config.getModuleInfo();
+          if (isValid()){
+            setValid(config.isValid() && info.isValid());
+            if (!isValid()){
+              setErrors(config.getErrors());
+              setErrors(info.getErrors());
+            }
+          }          
           serviceInfo.getProperties().addAll(info.getProperties());
           serviceInfo.setTypeAttributes(config.getConfigType(), info.getAttributes());
           configurationModules.put(config.getConfigType(), config);
@@ -384,4 +396,31 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> {
       serviceInfo.setTypeAttributes(config.getConfigType(), configInfo.getAttributes());
     }
   }
+
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+  
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }
+  
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 f938ba8..b35afb2 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
@@ -77,4 +77,16 @@ public interface StackDefinitionModule <T, I> {
    * @return the module state
    */
   public ModuleState getModuleState();
+  
+  /**
+   * 
+   * @return valid module flag
+   */
+  public boolean isValid();
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  public void setValid(boolean valid);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDirectory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDirectory.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDirectory.java
index b5930b2..d38cee9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDirectory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackDirectory.java
@@ -302,13 +302,15 @@ public class StackDirectory extends StackDefinitionDirectory {
         try {
           repoFile = unmarshaller.unmarshal(RepositoryXml.class, repositoryFile);
         } catch (JAXBException e) {
-          throw new AmbariException("Unable to parse repo file at location: " +
-              repositoryFile.getAbsolutePath(), e);
+          repoFile = new RepositoryXml();
+          repoFile.setValid(false);
+          repoFile.setErrors("Unable to parse repo file at location: " +
+              repositoryFile.getAbsolutePath());
         }
       }
     }
 
-    if (repoFile == null) {
+    if (repoFile == null || !repoFile.isValid()) {
       LOG.warn("No repository information defined for "
           + ", stackName=" + getStackDirName()
           + ", stackVersion=" + getPath()
@@ -334,8 +336,10 @@ public class StackDirectory extends StackDefinitionDirectory {
       try {
         metaInfoXml = unmarshaller.unmarshal(StackMetainfoXml.class, stackMetaInfoFile);
       } catch (JAXBException e) {
-        throw new AmbariException("Unable to parse stack metainfo.xml file at location: " +
-            stackMetaInfoFile.getAbsolutePath(), e);
+        metaInfoXml = new StackMetainfoXml();
+        metaInfoXml.setValid(false);
+        metaInfoXml.setErrors("Unable to parse stack metainfo.xml file at location: " +
+            stackMetaInfoFile.getAbsolutePath());
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 e55120e..33f1447 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
@@ -32,6 +32,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 
 /**
@@ -247,11 +248,21 @@ public class StackManager {
           String serviceVersion = serviceFolder.getName();
           ServiceDirectory serviceDirectory = new CommonServiceDirectory(serviceFolder.getPath());
           ServiceMetainfoXml metaInfoXml = serviceDirectory.getMetaInfoFile();
-          for (ServiceInfo serviceInfo : metaInfoXml.getServices()) {
-            ServiceModule serviceModule = new ServiceModule(stackContext, serviceInfo, serviceDirectory, true);
+          if (metaInfoXml != null) {
+            if (metaInfoXml.isValid()) {
+              for (ServiceInfo serviceInfo : metaInfoXml.getServices()) {
+                ServiceModule serviceModule = new ServiceModule(stackContext, serviceInfo, serviceDirectory, true);
 
-            String commonServiceKey = serviceInfo.getName() + StackManager.PATH_DELIMITER + serviceInfo.getVersion();
-            commonServiceModules.put(commonServiceKey, serviceModule);
+                String commonServiceKey = serviceInfo.getName() + StackManager.PATH_DELIMITER + serviceInfo.getVersion();
+                commonServiceModules.put(commonServiceKey, serviceModule);
+              }
+            } else {
+              ServiceModule serviceModule = new ServiceModule(stackContext, new ServiceInfo(), serviceDirectory, true);
+              serviceModule.setValid(false);
+              serviceModule.setErrors(metaInfoXml.getErrors());
+              commonServiceModules.put(metaInfoXml.getSchemaVersion(), serviceModule);
+              metaInfoXml.setSchemaVersion(null);
+            }
           }
         }
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 ce2ff2d..4181293 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
@@ -21,8 +21,10 @@ package org.apache.ambari.server.stack;
 import java.util.ArrayList;
 import java.util.Collection;
 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.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -70,7 +72,7 @@ import org.slf4j.LoggerFactory;
  * </p>
  *
  */
-public class StackModule extends BaseModule<StackModule, StackInfo> {
+public class StackModule extends BaseModule<StackModule, StackInfo> implements Validable {
 
   /**
    * Context which provides access to external functionality
@@ -103,6 +105,11 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
   private String id;
 
   /**
+   * validity flag
+   */
+  protected boolean valid = true;  
+  
+  /**
    * Logger
    */
   private final static Logger LOG = LoggerFactory.getLogger(StackModule.class);
@@ -314,10 +321,22 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
     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 + "'");
+      setValid(false);
+      stackInfo.setValid(false);
+      String error = "The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+          + stackInfo.getVersion() + "' extends a non-existent service: '" + parent + "'";
+      setErrors(error);
+      stackInfo.setErrors(error);
+    } else {
+      if (baseService.isValid()) {
+        service.resolve(baseService, allStacks, commonServices);
+      } else {
+        setValid(false);
+        stackInfo.setValid(false);
+        setErrors(baseService.getErrors());
+        stackInfo.setErrors(baseService.getErrors());        
+      }
     }
-    service.resolve(baseService, allStacks, commonServices);
   }
 
   /**
@@ -358,7 +377,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
     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);
   }
 
@@ -379,6 +398,10 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
     //odo: give additional thought on handling missing metainfo.xml
     StackMetainfoXml smx = stackDirectory.getMetaInfoFile();
     if (smx != null) {
+      if (!smx.isValid()) {
+        stackInfo.setValid(false);
+        stackInfo.setErrors(smx.getErrors());
+      }
       stackInfo.setMinUpgradeVersion(smx.getVersion().getUpgrade());
       stackInfo.setActive(smx.getVersion().isActive());
       stackInfo.setParentStackVersion(smx.getExtends());
@@ -392,13 +415,28 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
     }
 
     try {
+      //configurationModules
+      RepositoryXml rxml = stackDirectory.getRepoFile();
+      if (rxml != null && !rxml.isValid()) {
+        stackInfo.setValid(false);
+        stackInfo.setErrors(rxml.getErrors());
+      }
       // Read the service and available configs for this stack
       populateServices();
+      if (!stackInfo.isValid()) {
+        setValid(false);
+        setErrors(stackInfo.getErrors());
+      }
+      
       //todo: shouldn't blindly catch Exception, re-evaluate this.
     } catch (Exception e) {
-      LOG.error("Exception caught while populating services for stack: " +
-          stackInfo.getName() + "-" + stackInfo.getVersion());
-      e.printStackTrace();
+      String error = "Exception caught while populating services for stack: " +
+          stackInfo.getName() + "-" + stackInfo.getVersion();
+      setValid(false);
+      stackInfo.setValid(false);
+      setErrors(error);
+      stackInfo.setErrors(error);
+      LOG.error(error);
     }
   }
 
@@ -421,10 +459,24 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
     // unfortunately, we allow multiple services to be specified in the same metainfo.xml,
     // so we can't move the unmarshal logic into ServiceModule
     ServiceMetainfoXml metaInfoXml = serviceDirectory.getMetaInfoFile();
+    if (!metaInfoXml.isValid()){
+      stackInfo.setValid(metaInfoXml.isValid());
+      setValid(metaInfoXml.isValid());
+      stackInfo.setErrors(metaInfoXml.getErrors());
+      setErrors(metaInfoXml.getErrors());      
+      return;
+    }
     List<ServiceInfo> serviceInfos = metaInfoXml.getServices();
 
     for (ServiceInfo serviceInfo : serviceInfos) {
-      serviceModules.add(new ServiceModule(stackContext, serviceInfo, serviceDirectory));
+      ServiceModule serviceModule = new ServiceModule(stackContext, serviceInfo, serviceDirectory);
+      serviceModules.add(serviceModule);
+      if (!serviceModule.isValid()){
+        stackInfo.setValid(false);
+        setValid(false);
+        stackInfo.setErrors(serviceModule.getErrors());
+        setErrors(serviceModule.getErrors());        
+      }
     }
     addServices(serviceModules);
   }
@@ -439,6 +491,10 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
 
     if (configDirectory != null) {
       for (ConfigurationModule config : configDirectory.getConfigurationModules()) {
+        if (stackInfo.isValid()){
+          stackInfo.setValid(config.isValid());
+          stackInfo.setErrors(config.getErrors());
+        }
         stackInfo.getProperties().addAll(config.getModuleInfo().getProperties());
         stackInfo.setConfigTypeAttributes(config.getConfigType(), config.getModuleInfo().getAttributes());
         configurationModules.put(config.getConfigType(), config);
@@ -477,14 +533,20 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
    * @throws AmbariException if unable to resolve the stack
    */
   private void resolveStack(
-      StackModule stackToBeResolved, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
-      throws AmbariException {
+          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");
     }
+    if (!stackToBeResolved.isValid() || (stackToBeResolved.getModuleInfo() != null && !stackToBeResolved.getModuleInfo().isValid())) {
+      setValid(stackToBeResolved.isValid());
+      stackInfo.setValid(stackToBeResolved.stackInfo.isValid());
+      setErrors(stackToBeResolved.getErrors());
+      stackInfo.setErrors(stackToBeResolved.getErrors());
+    }
   }
 
   /**
@@ -588,4 +650,32 @@ public class StackModule extends BaseModule<StackModule, StackInfo> {
     stackInfo.getRoleCommandOrder().merge(parentStack.stackInfo.getRoleCommandOrder());
 
   }
+
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }
+  
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/stack/Validable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/Validable.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/Validable.java
new file mode 100644
index 0000000..e8b5f24
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/Validable.java
@@ -0,0 +1,48 @@
+/**
+ * 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 java.util.Collection;
+
+/**
+ *
+ * @author root
+ */
+public interface Validable {
+  
+  /**
+   * 
+   * @return valid xml flag
+   */
+  public boolean isValid();
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  public void setValid(boolean valid);
+  
+  public void setErrors(String error);
+  
+  public void setErrors(Collection error);
+  
+  public Collection getErrors();
+  
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
index d469c17..b1ee121 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
@@ -37,13 +37,14 @@ import javax.xml.bind.annotation.XmlElements;
 import javax.xml.bind.annotation.XmlTransient;
 
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.stack.Validable;
 import org.apache.ambari.server.state.stack.MetricDefinition;
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.map.annotate.JsonFilter;
 
 @XmlAccessorType(XmlAccessType.FIELD)
 @JsonFilter("propertiesfilter")
-public class ServiceInfo {
+public class ServiceInfo implements Validable{
 
   /**
    * Format version. Added at schema ver 2
@@ -110,8 +111,46 @@ public class ServiceInfo {
 
   @XmlTransient
   private File kerberosDescriptorFile = null;
+  
+  @XmlTransient
+  private boolean valid = true;
 
   /**
+   * 
+   * @return valid xml flag
+   */
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  @XmlTransient
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+  
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }
+  /**
    * Internal list of os-specific details (loaded from xml). Added at schema ver 2
    */
   @JsonIgnore

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
index c1c483f..4b6898a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
@@ -26,12 +26,14 @@ 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.controller.StackVersionResponse;
+import org.apache.ambari.server.stack.Validable;
 import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
 import org.apache.ambari.server.state.stack.UpgradePack;
 
-public class StackInfo implements Comparable<StackInfo>{
+public class StackInfo implements Comparable<StackInfo>, Validable{
   private String name;
   private String version;
   private String minUpgradeVersion;
@@ -46,8 +48,44 @@ public class StackInfo implements Comparable<StackInfo>{
   private Map<String, Map<String, Map<String, String>>> configTypes;
   private Map<String, UpgradePack> upgradePacks;
   private StackRoleCommandOrder roleCommandOrder;
+  private boolean valid = true;
 
   /**
+   * 
+   * @return valid xml flag
+   */
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }    
+
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+  
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }
+  
+  /**
    * Meaning: stores subpath from stack root to exact hooks folder for stack. These hooks are
    * applied to all commands for services in current stack.
    */
@@ -153,7 +191,7 @@ public class StackInfo implements Comparable<StackInfo>{
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder("Stack name:" + name + "\nversion:" +
-      version + "\nactive:" + active);
+      version + "\nactive:" + active + " \nvalid:" + isValid());
     if (services != null) {
       sb.append("\n\t\tService:");
       for (ServiceInfo service : services) {
@@ -215,7 +253,8 @@ public class StackInfo implements Comparable<StackInfo>{
         isActive(), getParentStackVersion(), getConfigTypeAttributes(),
         (stackDescriptorFileFilePath == null) ? null : new File(stackDescriptorFileFilePath),
         serviceDescriptorFiles,
-        null == upgradePacks ? Collections.<String>emptySet() : upgradePacks.keySet());
+        null == upgradePacks ? Collections.<String>emptySet() : upgradePacks.keySet(),
+        isValid(), getErrors());
   }
 
   public String getMinUpgradeVersion() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigurationXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigurationXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigurationXml.java
index 50ab901..ca33601 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigurationXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ConfigurationXml.java
@@ -18,15 +18,20 @@
 package org.apache.ambari.server.state.stack;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.xml.bind.annotation.XmlAnyAttribute;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.namespace.QName;
+import org.apache.ambari.server.stack.Validable;
 
 import org.apache.ambari.server.state.PropertyInfo;
 
@@ -34,13 +39,52 @@ import org.apache.ambari.server.state.PropertyInfo;
  * The elements within a service's configuration file.
  */
 @XmlRootElement(name="configuration")
-public class ConfigurationXml {
+public class ConfigurationXml implements Validable{
   
   @XmlAnyAttribute
   private Map<QName, String> attributes = new HashMap<QName, String>();
 
   @XmlElement(name="property")
   private List<PropertyInfo> properties = new ArrayList<PropertyInfo>();
+
+  @XmlTransient
+  private boolean valid = true;
+
+  /**
+   * 
+   * @return valid xml flag
+   */
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  @XmlTransient
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+ 
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
   
   /**
    * @return the list of properties contained in a configuration file

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
index fa5607b..eff063b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
@@ -18,26 +18,70 @@
 package org.apache.ambari.server.state.stack;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.apache.ambari.server.stack.Validable;
 
 /**
  * Represents the repository file <code>$STACK_VERSION/repos/repoinfo.xml</code>.
  */
 @XmlRootElement(name="reposinfo")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class RepositoryXml {
+public class RepositoryXml implements Validable{
 
   @XmlElement(name="latest")
   private String latestUri;
   @XmlElement(name="os")
   private List<Os> oses = new ArrayList<Os>();
 
+  @XmlTransient
+  private boolean valid = true;
+
+  /**
+   * 
+   * @return valid xml flag
+   */
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }    
+  
+  @XmlTransient
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  } 
+ 
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
+  
   /**
    * @return the latest URI defined, if any.
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
index 4d3587e..56dac8a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
@@ -17,10 +17,14 @@
  */
 package org.apache.ambari.server.state.stack;
 
+import java.util.Collection;
+import java.util.HashSet;
 import org.apache.ambari.server.state.ServiceInfo;
 
 import javax.xml.bind.annotation.*;
 import java.util.List;
+import java.util.Set;
+import org.apache.ambari.server.stack.Validable;
 
 /**
  * Represents the <code>$SERVICE_HOME/metainfo.xml</code> file.
@@ -29,7 +33,7 @@ import java.util.List;
  */
 @XmlRootElement(name="metainfo")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class ServiceMetainfoXml {
+public class ServiceMetainfoXml implements Validable{
 
   private String schemaVersion;
 
@@ -37,6 +41,45 @@ public class ServiceMetainfoXml {
   @XmlElements(@XmlElement(name="service"))
   private List<ServiceInfo> services;
   
+  @XmlTransient
+  private boolean valid = true;
+
+  /**
+   * 
+   * @return valid xml flag
+   */
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+
+  @XmlTransient
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  } 
+
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }  
+  
   /**
    * @return the list of services for the metainfo file
    */
@@ -48,4 +91,9 @@ public class ServiceMetainfoXml {
     return schemaVersion;
   }
 
+  public void setSchemaVersion(String schemaVersion) {
+    this.schemaVersion = schemaVersion;
+  }
+
+  
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/java/org/apache/ambari/server/state/stack/StackMetainfoXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/StackMetainfoXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/StackMetainfoXml.java
index cd02f45..55b1b9b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/StackMetainfoXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/StackMetainfoXml.java
@@ -17,23 +17,67 @@
  */
 package org.apache.ambari.server.state.stack;
 
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import org.apache.ambari.server.stack.Validable;
 
 /**
  * Represents the stack <code>metainfo.xml</code> file.
  */
 @XmlRootElement(name="metainfo")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class StackMetainfoXml {
+public class StackMetainfoXml implements Validable{
   
   @XmlElement(name="extends")
   private String extendsVersion = null;
   
   @XmlElement(name="versions")
   private Version version = new Version();
+
+  @XmlTransient
+  private boolean valid = true;
+
+  /**
+   * 
+   * @return valid xml flag
+   */
+  @Override
+  public boolean isValid() {
+    return valid;
+  }
+
+  /**
+   * 
+   * @param valid set validity flag
+   */
+  @Override
+  public void setValid(boolean valid) {
+    this.valid = valid;
+  }
+  
+  @XmlTransient
+  private Set<String> errorSet = new HashSet<String>();
+  
+  @Override
+  public void setErrors(String error) {
+    errorSet.add(error);
+  }
+
+  @Override
+  public Collection getErrors() {
+    return errorSet;
+  }   
+
+  @Override
+  public void setErrors(Collection error) {
+    this.errorSet.addAll(error);
+  }
   
   /**
    * @return the parent stack version number

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index cd50968..cdb2bd6 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -202,6 +202,8 @@
         "Versions/stack_version",
         "Versions/min_upgrade_version",
         "Versions/active",
+        "Versions/valid",
+        "Versions/stack-errors",
         "Versions/parent_stack_version",
         "Versions/config_types",
         "Versions/kerberos_descriptor",

http://git-wip-us.apache.org/repos/asf/ambari/blob/a3e1edb3/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 7b0d80c..0d944ab 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
@@ -803,13 +803,12 @@ public class AmbariMetaInfoTest {
     }
     LOG.info("Stacks file " + stackRoot.getAbsolutePath());
 
-    try {
-      createAmbariMetaInfo(stackRoot, version, true);
-      fail("Exception expected due to bad stack");
-    } catch(AmbariException e) {
-      e.printStackTrace();
-      assertTrue(e.getCause() instanceof JAXBException);
-    }
+
+    TestAmbariMetaInfo ambariMetaInfo = createAmbariMetaInfo(stackRoot, version, true);
+    Assert.assertEquals(1, ambariMetaInfo.getStackManager().getStacks().size());
+    Assert.assertEquals(false, ambariMetaInfo.getStackManager().getStack("HDP", "0.1").isValid());
+    Assert.assertEquals(2, ambariMetaInfo.getStackManager().getStack("HDP", "0.1").getErrors().size());
+
   }
 
   @Test


Mime
View raw message