Repository: ambari
Updated Branches:
  refs/heads/trunk 354b0a975 -> 7d70695a0


AMBARI-15592: Auto-start services - support blueprint deployment


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

Branch: refs/heads/trunk
Commit: 7d70695a0d80189ef7f72184d1908997afa694b4
Parents: 354b0a9
Author: Nahappan Somasundaram <[email protected]>
Authored: Tue Mar 29 19:12:05 2016 -0700
Committer: Nahappan Somasundaram <[email protected]>
Committed: Thu Mar 31 11:48:57 2016 -0700

----------------------------------------------------------------------
 .../server/orm/entities/BlueprintEntity.java    |  21 +++
 .../orm/entities/BlueprintSettingEntity.java    | 142 ++++++++++++++++++
 .../ambari/server/topology/AmbariContext.java   |   3 +-
 .../ambari/server/topology/Blueprint.java       |  20 +++
 .../server/topology/BlueprintFactory.java       |   7 +-
 .../ambari/server/topology/BlueprintImpl.java   | 118 ++++++++++++++-
 .../apache/ambari/server/topology/Setting.java  |  75 ++++++++++
 .../ambari/server/topology/SettingFactory.java  | 101 +++++++++++++
 .../server/upgrade/UpgradeCatalog240.java       |  55 +++++--
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  11 ++
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  10 ++
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  10 ++
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  13 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  14 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  10 ++
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  13 +-
 .../src/main/resources/META-INF/persistence.xml |   1 +
 .../src/main/resources/properties.json          |   3 +-
 .../orm/entities/BlueprintEntityTest.java       |  11 ++
 .../entities/BlueprintSettingEntityTest.java    |  72 +++++++++
 .../server/topology/SettingFactoryTest.java     | 149 +++++++++++++++++++
 .../ambari/server/topology/SettingTest.java     |  99 ++++++++++++
 .../server/upgrade/UpgradeCatalog240Test.java   |  35 ++++-
 23 files changed, 968 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
index 8578d6b..94b59da 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
@@ -71,6 +71,9 @@ public class BlueprintEntity {
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint")
   private Collection<BlueprintConfigEntity> configurations;
 
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint")
+  private Collection<BlueprintSettingEntity> settings;
+
 
   /**
    * Get the blueprint name.
@@ -145,6 +148,24 @@ public class BlueprintEntity {
     this.configurations = configurations;
   }
 
+  /**
+   * Get the collection of associated setting.
+   *
+   * @return collection of setting
+   */
+  public Collection<BlueprintSettingEntity> getSettings() {
+    return settings;
+  }
+
+  /**
+   * Set the settings collection.
+   *
+   * @param settings collection of associated setting
+   */
+  public void setSettings(Collection<BlueprintSettingEntity> settings) {
+    this.settings = settings;
+  }
+
   public SecurityType getSecurityType() {
     return securityType;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java
new file mode 100644
index 0000000..776e5e9
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+/**
+ * Represents a blueprint setting.
+ */
+@Table(name = "blueprint_setting", uniqueConstraints =
+@UniqueConstraint(
+        name = "UQ_blueprint_setting_name", columnNames = {"blueprint_name", 
"setting_name"}
+  )
+)
+
+@TableGenerator(name = "blueprint_setting_id_generator",
+        table = "ambari_sequences", pkColumnName = "sequence_name", 
valueColumnName = "sequence_value",
+        pkColumnValue = "blueprint_setting_id_seq", initialValue = 0)
+
+@Entity
+public class BlueprintSettingEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = 
"blueprint_setting_id_generator")
+  private long id;
+
+  @Column(name = "blueprint_name", nullable = false, insertable = false, 
updatable = false)
+  private String blueprintName;
+
+  @Column(name = "setting_name", nullable = false, insertable = true, 
updatable = false)
+  private String settingName;
+
+  @Column(name = "setting_data", nullable = false, insertable = true, 
updatable = false)
+  @Basic(fetch = FetchType.LAZY)
+  @Lob
+  private String settingData;
+
+  @ManyToOne
+  @JoinColumn(name = "blueprint_name", referencedColumnName = 
"blueprint_name", nullable = false)
+  private BlueprintEntity blueprint;
+
+  /**
+   * Get the blueprint entity instance.
+   *
+   * @return blueprint entity
+   */
+  public BlueprintEntity getBlueprintEntity() {
+    return blueprint;
+  }
+
+  /**
+   * Set the blueprint entity instance.
+   *
+   * @param entity  blueprint entity
+   */
+  public void setBlueprintEntity(BlueprintEntity entity) {
+    this.blueprint = entity;
+  }
+
+  /**
+   * Get the name of the associated blueprint.
+   *
+   * @return blueprint name
+   */
+  public String getBlueprintName() {
+    return blueprintName;
+  }
+
+  /**
+   * Set the name of the associated blueprint.
+   * '
+   * @param blueprintName  blueprint name
+   */
+  public void setBlueprintName(String blueprintName) {
+    this.blueprintName = blueprintName;
+  }
+
+  /**
+   * Get the setting name.
+   *
+   * @return setting name
+   */
+  public String getSettingName() {
+    return settingName;
+  }
+
+  /**
+   * Set the setting name.
+   *
+   * @param settingName  setting name
+   */
+  public void setSettingName(String settingName) {
+    this.settingName = settingName;
+  }
+
+  /**
+   * Get the setting data.
+   *
+   * @return setting data in json format
+   */
+  public String getSettingData() {
+    return settingData;
+  }
+
+  /**
+   * Set the setting data.
+   *
+   * @param settingData  all config data in json format
+   */
+  public void setSettingData(String settingData) {
+    this.settingData = settingData;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
index a5e2fa1..dd2b7c6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
@@ -191,7 +191,8 @@ public class AmbariContext {
     for (String service : services) {
       serviceRequests.add(new ServiceRequest(clusterName, service, null));
       for (String component : topology.getBlueprint().getComponents(service)) {
-        componentRequests.add(new ServiceComponentRequest(clusterName, 
service, component, null));
+        String recoveryEnabled = 
String.valueOf(topology.getBlueprint().isRecoveryEnabled(service, component));
+        componentRequests.add(new ServiceComponentRequest(clusterName, 
service, component, null, recoveryEnabled));
       }
     }
     try {

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
index 11311db..2fc74de 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java
@@ -62,6 +62,15 @@ public interface Blueprint {
   public Configuration getConfiguration();
 
   /**
+   * Get the Blueprint cluster scoped setting.
+   * The blueprint cluster scoped setting has the setting properties
+   * with the setting names associated with the blueprint.
+   *
+   * @return blueprint cluster scoped setting
+   */
+  public Setting getSetting();
+
+  /**
    * Get all of the services represented in the blueprint.
    *
    * @return collection of all represented service names
@@ -78,6 +87,17 @@ public interface Blueprint {
   public Collection<String> getComponents(String service);
 
   /**
+   * Get whether a component is enabled for auto start.
+   *
+   * @param serviceName - Service name.
+   * @param componentName - Component name.
+   *
+   * @return True or false.
+   */
+  public boolean isRecoveryEnabled(String serviceName, String componentName);
+
+
+  /**
    * Get the stack associated with the blueprint.
    *
    * @return associated stack

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java
index cca28ca..cb9d239 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java
@@ -66,6 +66,8 @@ public class BlueprintFactory {
   protected static final String PROPERTIES_PROPERTY_ID = "properties";
   protected static final String PROPERTIES_ATTRIBUTES_PROPERTY_ID = 
"properties_attributes";
 
+  protected static final String SETTINGS_PROPERTY_ID = "settings";
+
   private static BlueprintDAO blueprintDAO;
   private ConfigurationFactory configFactory = new ConfigurationFactory();
 
@@ -104,9 +106,10 @@ public class BlueprintFactory {
     Stack stack = createStack(properties);
     Collection<HostGroup> hostGroups = processHostGroups(name, stack, 
properties);
     Configuration configuration = 
configFactory.getConfiguration((Collection<Map<String, String>>)
-        properties.get(CONFIGURATION_PROPERTY_ID));
+            properties.get(CONFIGURATION_PROPERTY_ID));
+    Setting setting =  SettingFactory.getSetting((Collection<Map<String, 
Object>>) properties.get(SETTINGS_PROPERTY_ID));
 
-    return new BlueprintImpl(name, hostGroups, stack, configuration, 
securityConfiguration);
+    return new BlueprintImpl(name, hostGroups, stack, configuration, 
securityConfiguration, setting);
   }
 
   protected Stack createStack(Map<String, Object> properties) throws 
NoSuchStackException {

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
index bea0364..0bb4874 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
@@ -27,17 +27,21 @@ import org.apache.ambari.server.controller.internal.Stack;
 import org.apache.ambari.server.orm.entities.BlueprintConfigEntity;
 import org.apache.ambari.server.orm.entities.BlueprintConfiguration;
 import org.apache.ambari.server.orm.entities.BlueprintEntity;
+import org.apache.ambari.server.orm.entities.BlueprintSettingEntity;
 import org.apache.ambari.server.orm.entities.HostGroupComponentEntity;
 import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
 import org.apache.ambari.server.orm.entities.HostGroupEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.stack.NoSuchStackException;
+import org.apache.commons.lang.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Blueprint implementation.
@@ -50,6 +54,7 @@ public class BlueprintImpl implements Blueprint {
   private Configuration configuration;
   private BlueprintValidator validator;
   private SecurityConfiguration security;
+  private Setting setting;
 
   public BlueprintImpl(BlueprintEntity entity) throws NoSuchStackException {
     this.name = entity.getBlueprintName();
@@ -65,9 +70,16 @@ public class BlueprintImpl implements Blueprint {
     parseBlueprintHostGroups(entity);
     
configuration.setParentConfiguration(stack.getConfiguration(getServices()));
     validator = new BlueprintValidatorImpl(this);
+    processSetting(entity.getSettings());
   }
 
-  public BlueprintImpl(String name, Collection<HostGroup> groups, Stack stack, 
Configuration configuration, SecurityConfiguration security) {
+  public BlueprintImpl(String name, Collection<HostGroup> groups, Stack stack, 
Configuration configuration,
+                       SecurityConfiguration security) {
+    this(name, groups, stack, configuration, security, null);
+  }
+
+  public BlueprintImpl(String name, Collection<HostGroup> groups, Stack stack, 
Configuration configuration,
+                       SecurityConfiguration security, Setting setting) {
     this.name = name;
     this.stack = stack;
     this.security = security;
@@ -82,6 +94,7 @@ public class BlueprintImpl implements Blueprint {
       
configuration.setParentConfiguration(stack.getConfiguration(getServices()));
     }
     validator = new BlueprintValidatorImpl(this);
+    this.setting = setting;
   }
 
   public String getName() {
@@ -117,6 +130,11 @@ public class BlueprintImpl implements Blueprint {
     return configuration;
   }
 
+  @Override
+  public Setting getSetting() {
+    return setting;
+  }
+
   /**
    * Get all services represented in blueprint.
    *
@@ -141,6 +159,50 @@ public class BlueprintImpl implements Blueprint {
     return components;
   }
 
+  /**
+   * Get whether the specified component in the service is enabled
+   * for auto start.
+   *
+   * @param serviceName - Service name.
+   * @param componentName - Component name.
+   *
+   * @return True or false.
+   */
+  @Override
+  public boolean isRecoveryEnabled(String serviceName, String componentName) {
+    if (setting == null)
+      return false;
+
+    Set<HashMap<String, String>> settingValue;
+
+    // If component name was specified in the list of "component_settings",
+    // determine if recovery_enabled is true or false and return it.
+    settingValue = 
setting.getSettingValue(Setting.SETTING_NAME_COMPONENT_SETTINGS);
+    for (Map<String, String> setting : settingValue) {
+      String name = setting.get(Setting.SETTING_NAME_NAME);
+      if (StringUtils.equals(name, componentName)) {
+        return 
Boolean.parseBoolean(setting.get(Setting.SETTING_NAME_RECOVERY_ENABLED));
+      }
+    }
+
+    // If component name is not specified, look up it's service.
+    settingValue = 
setting.getSettingValue(Setting.SETTING_NAME_SERVICE_SETTINGS);
+    for ( Map<String, String> setting : settingValue){
+      String name = setting.get(Setting.SETTING_NAME_NAME);
+      if (StringUtils.equals(name, serviceName)) {
+        return 
Boolean.parseBoolean(setting.get(Setting.SETTING_NAME_RECOVERY_ENABLED));
+      }
+    }
+
+    // If service name is not specified, look up the cluster setting.
+    settingValue = 
setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS);
+    for (Map<String, String> setting : settingValue) {
+      return 
Boolean.parseBoolean(setting.get(Setting.SETTING_NAME_RECOVERY_ENABLED));
+    }
+
+    return false;
+  }
+
   @Override
   public Stack getStack() {
     return stack;
@@ -209,6 +271,7 @@ public class BlueprintImpl implements Blueprint {
 
     createHostGroupEntities(entity);
     createBlueprintConfigEntities(entity);
+    createBlueprintSettingEntities(entity);
 
     return entity;
   }
@@ -255,6 +318,17 @@ public class BlueprintImpl implements Blueprint {
   }
 
   /**
+   * Process blueprint setting.
+   *
+   * @param blueprintSetting
+   */
+  private void processSetting(Collection<BlueprintSettingEntity> 
blueprintSetting) {
+    if (blueprintSetting != null) {
+      setting = new Setting(parseSetting(blueprintSetting));
+    }
+  }
+
+  /**
    * Obtain configuration as a map of config type to corresponding properties.
    *
    * @return map of config type to map of properties
@@ -266,13 +340,31 @@ public class BlueprintImpl implements Blueprint {
     for (BlueprintConfiguration config : configs) {
       String type = config.getType();
       Map<String, String> typeProperties = gson.<Map<String, String>>fromJson(
-          config.getConfigData(), Map.class);
+              config.getConfigData(), Map.class);
       properties.put(type, typeProperties);
     }
     return properties;
   }
 
   /**
+   * Deserialization: Obtain setting as a map of setting name to corresponding 
properties.
+   *
+   * @return map of setting name to map of properties
+   */
+  private Map<String, Set<HashMap<String, String>>> 
parseSetting(Collection<BlueprintSettingEntity> blueprintSetting) {
+
+    Map<String, Set<HashMap<String, String>>> properties = new HashMap<String, 
Set<HashMap<String, String>>>();
+    Gson gson = new Gson();
+    for (BlueprintSettingEntity setting : blueprintSetting) {
+      String settingName = setting.getSettingName();
+      Set<HashMap<String, String>> settingProperties = 
gson.<Set<HashMap<String, String>>>fromJson(
+              setting.getSettingData(), Set.class);
+      properties.put(settingName, settingProperties);
+    }
+    return properties;
+  }
+
+  /**
    * Process cluster scoped configuration attributes contained in blueprint.
    *
    * @return cluster scoped property attributes contained within in blueprint
@@ -417,4 +509,26 @@ public class BlueprintImpl implements Blueprint {
     blueprintEntity.setConfigurations(configEntityMap.values());
   }
 
+  /**
+   * Populate setting for serialization to DB.
+   */
+  private void createBlueprintSettingEntities(BlueprintEntity blueprintEntity) 
{
+    Gson jsonSerializer = new Gson();
+    Setting blueprintSetting = getSetting();
+    if (blueprintSetting != null) {
+      Map<String, BlueprintSettingEntity> settingEntityMap = new HashMap<>();
+      for (Map.Entry<String, Set<HashMap<String, String>>> propEntry : 
blueprintSetting.getProperties().entrySet()) {
+        String settingName = propEntry.getKey();
+        Set<HashMap<String, String>> properties = propEntry.getValue();
+
+        BlueprintSettingEntity settingEntity = new BlueprintSettingEntity();
+        settingEntityMap.put(settingName, settingEntity);
+        settingEntity.setBlueprintName(getName());
+        settingEntity.setBlueprintEntity(blueprintEntity);
+        settingEntity.setSettingName(settingName);
+        settingEntity.setSettingData(jsonSerializer.toJson(properties));
+      }
+      blueprintEntity.setSettings(settingEntityMap.values());
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
new file mode 100644
index 0000000..c03d833
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.topology;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class Setting {
+  /**
+   * Settings for this configuration instance
+   */
+  private Map<String, Set<HashMap<String, String>>> properties;
+
+  public static final String SETTING_NAME_RECOVERY_SETTINGS = 
"recovery_settings";
+
+  public static final String SETTING_NAME_SERVICE_SETTINGS = 
"service_settings";
+
+  public static final String SETTING_NAME_COMPONENT_SETTINGS = 
"component_settings";
+
+  public static final String SETTING_NAME_RECOVERY_ENABLED = 
"recovery_enabled";
+
+  public static final String SETTING_NAME_NAME = "name";
+
+  /**
+   * Settings.
+   *
+   * @param properties  setting name-->Set(property name-->property value)
+   */
+  public Setting(Map<String, Set<HashMap<String, String>>> properties) {
+
+    this.properties = properties;
+  }
+
+  /**
+   * Get the properties for this instance.
+   *
+   * @return map of properties for this settings instance keyed by setting 
name.
+   */
+  public Map<String, Set<HashMap<String, String>>> getProperties() {
+    return properties;
+  }
+
+  /**
+   * Get the setting properties for a specified setting name.
+   *
+   * @param settingName
+   * @return Set of Map of properties.
+   */
+  public Set<HashMap<String, String>> getSettingValue(String settingName) {
+    if (properties.containsKey(settingName)) {
+      return properties.get(settingName);
+    }
+
+    return Collections.emptySet();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java
new file mode 100644
index 0000000..4aca1ca
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java
@@ -0,0 +1,101 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.topology;
+
+import com.google.inject.Singleton;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Creates the Setting object from the parsed blueprint. Expects the settings 
JSON
+ * that was parsed to follow the schema here:
+ *
+ *   "settings" : [
+ *     {
+ *     "recovery_settings" : [{
+ *     "recovery_enabled" : "true"
+ *     }
+ *    ]
+ *    },
+ *    {
+ *      "service_settings" : [
+ *      {
+ *        "name" : "HDFS",
+ *        "recovery_enabled" : "false"
+ *      },
+ *      {
+ *        "name" : "TEZ",
+ *        "recovery_enabled" : "false"
+ *      }
+ *      ]
+ *     },
+ *     {
+ *       "component_settings" : [
+ *       {
+ *         "name" : "DATANODE",
+ *         "recovery_enabled" : "true"
+ *       }
+ *       ]
+ *     }
+ *    ]
+ */
+@Singleton
+public class SettingFactory {
+  /**
+   * Attempts to build the list of settings in the following format:
+   * setting_name1-->[propertyName1-->propertyValue1, 
propertyName2-->propertyValue2]
+   * @param blueprintSetting
+   * @return
+   */
+  public static Setting getSetting(Collection<Map<String, Object>> 
blueprintSetting) {
+    Map<String, Set<HashMap<String, String>>> properties = new HashMap<>();
+    Setting setting = new Setting(properties);
+
+    if (blueprintSetting != null) {
+      for (Map<String, Object> settingMap : blueprintSetting) {
+        for (Map.Entry<String, Object> entry : settingMap.entrySet()) {
+          final String[] propertyNames = entry.getKey().split("/");
+          Set<HashMap<String, String>> settingValue;
+          if (entry.getValue() instanceof Set) {
+            settingValue = (HashSet<HashMap<String, String>>)entry.getValue();
+          }
+          else if (propertyNames.length > 1){
+            HashMap<String, String> property = new HashMap<>();
+            property.put(propertyNames[1], String.valueOf(entry.getValue()));
+            settingValue = properties.get(propertyNames[0]);
+            if (settingValue == null) {
+              settingValue = new HashSet<>();
+            }
+            settingValue.add(property);
+          }
+          else {
+            throw new IllegalArgumentException("Invalid setting schema: " + 
String.valueOf(entry.getValue()));
+          }
+          properties.put(propertyNames[0], settingValue);
+        }
+      }
+    }
+
+    return setting;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
index d8b84ec..a73a526 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
@@ -83,7 +83,12 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
   protected static final String CLUSTER_TABLE = "clusters";
   protected static final String CLUSTER_UPGRADE_ID_COLUMN = "upgrade_id";
   public static final String DESIRED_VERSION_COLUMN_NAME = "desired_version";
-
+  public static final String BLUEPRINT_SETTING_TABLE = "blueprint_setting";
+  public static final String BLUEPRINT_NAME_COL = "blueprint_name";
+  public static final String SETTING_NAME_COL = "setting_name";
+  public static final String SETTING_DATA_COL = "setting_data";
+  public static final String ID = "id";
+  public static final String BLUEPRINT_TABLE = "blueprint";
 
   @Inject
   PermissionDAO permissionDAO;
@@ -96,7 +101,6 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
    */
   private static final Logger LOG = 
LoggerFactory.getLogger(UpgradeCatalog240.class);
 
-  private static final String ID = "id";
   private static final String SETTING_TABLE = "setting";
 
   protected static final String SERVICE_COMPONENT_DESIRED_STATE_TABLE = 
"servicecomponentdesiredstate";
@@ -146,6 +150,7 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
     createServiceComponentHistoryTable();
     updateClusterTableDDL();
     updateAlertDefinitionTable();
+    createBlueprintSettingTable();
   }
 
   private void updateClusterTableDDL() throws SQLException {
@@ -199,7 +204,7 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
     String administratorPermissionId = 
permissionDAO.findPermissionByNameAndType("AMBARI.ADMINISTRATOR",
         resourceTypeDAO.findByName("AMBARI")).getId().toString();
     dbAccessor.insertRowIfMissing("permission_roleauthorization", new 
String[]{"permission_id", "authorization_id"},
-      new String[]{"'" + administratorPermissionId + "'", 
"'AMBARI.MANAGE_SETTINGS'"}, false);
+            new String[]{"'" + administratorPermissionId + "'", 
"'AMBARI.MANAGE_SETTINGS'"}, false);
   }
 
   /**
@@ -238,7 +243,7 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
     permissionId = 
permissionDAO.findPermissionByNameAndType("CLUSTER.OPERATOR",
       resourceTypeDAO.findByName("CLUSTER")).getId().toString();
     dbAccessor.insertRowIfMissing("permission_roleauthorization", new 
String[]{"permission_id", "authorization_id"},
-      new String[]{"'" + permissionId + "'", 
"'CLUSTER.MANAGE_USER_PERSISTED_DATA'"}, false);
+            new String[]{"'" + permissionId + "'", 
"'CLUSTER.MANAGE_USER_PERSISTED_DATA'"}, false);
 
     permissionId = 
permissionDAO.findPermissionByNameAndType("AMBARI.ADMINISTRATOR",
       resourceTypeDAO.findByName("AMBARI")).getId().toString();
@@ -480,15 +485,15 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
     dbAccessor.executeUpdate(String.format(updateStatement,
         2, PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION_NAME));
     dbAccessor.executeUpdate(String.format(updateStatement,
-        3, PermissionEntity.CLUSTER_OPERATOR_PERMISSION_NAME));
+            3, PermissionEntity.CLUSTER_OPERATOR_PERMISSION_NAME));
     dbAccessor.executeUpdate(String.format(updateStatement,
-        4, PermissionEntity.SERVICE_ADMINISTRATOR_PERMISSION_NAME));
+            4, PermissionEntity.SERVICE_ADMINISTRATOR_PERMISSION_NAME));
     dbAccessor.executeUpdate(String.format(updateStatement,
-        5, PermissionEntity.SERVICE_OPERATOR_PERMISSION_NAME));
+            5, PermissionEntity.SERVICE_OPERATOR_PERMISSION_NAME));
     dbAccessor.executeUpdate(String.format(updateStatement,
-        6, PermissionEntity.CLUSTER_USER_PERMISSION_NAME));
+            6, PermissionEntity.CLUSTER_USER_PERMISSION_NAME));
     dbAccessor.executeUpdate(String.format(updateStatement,
-      7, PermissionEntity.VIEW_USER_PERMISSION_NAME));
+            7, PermissionEntity.VIEW_USER_PERMISSION_NAME));
   }
 
   /**
@@ -642,7 +647,7 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
         "from_stack_id", STACK_TABLE, "stack_id", false);
 
     dbAccessor.addFKConstraint(SERVICE_COMPONENT_HISTORY_TABLE, 
"FK_sc_history_to_stack_id",
-        "to_stack_id", STACK_TABLE, "stack_id", false);
+            "to_stack_id", STACK_TABLE, "stack_id", false);
 
     addSequence("servicecomponent_history_id_seq", 0L, false);
   }
@@ -658,7 +663,7 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
             new DBColumnInfo(RECOVERY_ENABLED_COL, Short.class, null, 0, 
false));
 
     dbAccessor.addColumn(SERVICE_COMPONENT_DESIRED_STATE_TABLE,
-      new DBColumnInfo(DESIRED_VERSION_COLUMN_NAME, String.class, 255, 
State.UNKNOWN.toString(), false));
+            new DBColumnInfo(DESIRED_VERSION_COLUMN_NAME, String.class, 255, 
State.UNKNOWN.toString(), false));
   }
 
   /**
@@ -691,7 +696,7 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
             String content = amsEnv.getProperties().get("content");
             if (content != null && !content.contains("AMS_INSTANCE_NAME")) {
               String newContent = content + "\n # AMS instance name\n" +
-                "export AMS_INSTANCE_NAME={{hostname}}\n";
+                      "export AMS_INSTANCE_NAME={{hostname}}\n";
 
               updateConfigurationProperties("ams-env", 
Collections.singletonMap("content", newContent), true, true);
             }
@@ -700,4 +705,30 @@ public class UpgradeCatalog240 extends 
AbstractUpgradeCatalog {
       }
     }
   }
+
+  /**
+   * Create blueprint_setting table for storing the "settings" section
+   * in the blueprint. Auto start information is specified in the "settings" 
section.
+   *
+   * @throws SQLException
+   */
+  private void createBlueprintSettingTable() throws SQLException {
+    List<DBColumnInfo> columns = new ArrayList<>();
+
+    //  Add blueprint_setting table
+    LOG.info("Creating " + BLUEPRINT_SETTING_TABLE + " table");
+
+    columns.add(new DBColumnInfo(ID, Long.class, null, null, false));
+    columns.add(new DBColumnInfo(BLUEPRINT_NAME_COL, String.class, 255, null, 
false));
+    columns.add(new DBColumnInfo(SETTING_NAME_COL, String.class, 255, null, 
false));
+    columns.add(new DBColumnInfo(SETTING_DATA_COL, char[].class, null, null, 
false));
+    dbAccessor.createTable(BLUEPRINT_SETTING_TABLE, columns);
+
+    dbAccessor.addPKConstraint(BLUEPRINT_SETTING_TABLE, 
"PK_blueprint_setting", ID);
+    dbAccessor.addUniqueConstraint(BLUEPRINT_SETTING_TABLE, 
"UQ_blueprint_setting_name", BLUEPRINT_NAME_COL, SETTING_NAME_COL);
+    dbAccessor.addFKConstraint(BLUEPRINT_SETTING_TABLE, 
"FK_blueprint_setting_name",
+            BLUEPRINT_NAME_COL, BLUEPRINT_TABLE, BLUEPRINT_NAME_COL, false);
+
+    addSequence("blueprint_setting_id_seq", 0L, false);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index 4a0479e..79f41e3 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -421,6 +421,15 @@ CREATE TABLE blueprint_configuration (
   config_attributes VARCHAR(3000),
   PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE blueprint_settings (
+  id BIGINT NOT NULL,
+  blueprint_name varchar(255) NOT NULL,
+  setting_name varchar(255) NOT NULL,
+  setting_data CLOB NOT NULL,
+  CONSTRAINT PK_blueprint_settings PRIMARY KEY (id),
+  CONSTRAINT UQ_blueprint_settings_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_settings_name FOREIGN KEY (blueprint_name) 
REFERENCES blueprint(blueprint_name));
+
 CREATE TABLE hostgroup_configuration (
   blueprint_name VARCHAR(255) NOT NULL,
   hostgroup_name VARCHAR(255) NOT NULL,
@@ -1070,6 +1079,8 @@ INSERT INTO ambari_sequences (sequence_name, 
sequence_value)
   select 'servicecomponentdesiredstate_id_seq', 0 FROM SYSIBM.SYSDUMMY1
   union all
   select 'servicecomponent_history_id_seq', 0 FROM SYSIBM.SYSDUMMY1;
+  union all
+  select 'blueprint_settings_id_seq', 0 FROM SYSIBM.SYSDUMMY1;
 
 
 INSERT INTO adminresourcetype (resource_type_id, resource_type_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index e40165d..90fc375 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -430,6 +430,15 @@ CREATE TABLE blueprint_configuration (
   config_attributes LONGTEXT,
   PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE blueprint_setting (
+  id BIGINT NOT NULL,
+  blueprint_name VARCHAR(100) NOT NULL,
+  setting_name VARCHAR(100) NOT NULL,
+  setting_data MEDIUMTEXT NOT NULL,
+  CONSTRAINT PK_blueprint_setting PRIMARY KEY (id),
+  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES 
blueprint(blueprint_name));
+
 CREATE TABLE hostgroup_configuration (
   blueprint_name VARCHAR(100) NOT NULL,
   hostgroup_name VARCHAR(100) NOT NULL,
@@ -1035,6 +1044,7 @@ INSERT INTO ambari_sequences(sequence_name, 
sequence_value) values ('setting_id_
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('hostcomponentstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('servicecomponentdesiredstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('servicecomponent_history_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('blueprint_setting_id_seq', 0);
 
 insert into adminresourcetype (resource_type_id, resource_type_name)
   select 1, 'AMBARI'

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index e85ea49..d1880bc 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -421,6 +421,15 @@ CREATE TABLE blueprint_configuration (
   config_attributes CLOB,
   PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE blueprint_setting (
+  id NUMBER(19) NOT NULL,
+  blueprint_name VARCHAR2(255) NOT NULL,
+  setting_name VARCHAR2(255) NOT NULL,
+  setting_data CLOB NOT NULL,
+  CONSTRAINT PK_blueprint_setting PRIMARY KEY (id),
+  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES 
blueprint(blueprint_name));
+
 CREATE TABLE hostgroup_configuration (
   blueprint_name VARCHAR2(255) NOT NULL,
   hostgroup_name VARCHAR2(255) NOT NULL,
@@ -1026,6 +1035,7 @@ INSERT INTO ambari_sequences(sequence_name, 
sequence_value) values ('setting_id_
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('hostcomponentstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('servicecomponentdesiredstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('servicecomponent_history_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('blueprint_setting_id_seq', 0);
 
 INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', 
'${ambariSchemaVersion}');
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 8bcda31..dd1fe5f 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -422,6 +422,15 @@ CREATE TABLE blueprint_configuration (
   config_attributes TEXT,
   PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE blueprint_setting (
+  id BIGINT NOT NULL,
+  blueprint_name varchar(255) NOT NULL,
+  setting_name varchar(255) NOT NULL,
+  setting_data TEXT NOT NULL,
+  CONSTRAINT PK_blueprint_setting PRIMARY KEY(id),
+  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES 
blueprint(blueprint_name));
+
 CREATE TABLE hostgroup_configuration (
   blueprint_name VARCHAR(255) NOT NULL,
   hostgroup_name VARCHAR(255) NOT NULL,
@@ -1076,7 +1085,9 @@ INSERT INTO ambari_sequences (sequence_name, 
sequence_value)
   union all
   select 'servicecomponentdesiredstate_id_seq', 0
   union all
-  select 'servicecomponent_history_id_seq', 0;
+  select 'servicecomponent_history_id_seq', 0
+  union all
+  select 'blueprint_setting_id_seq', 0;
 
 
 INSERT INTO adminresourcetype (resource_type_id, resource_type_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index c7d7cff..e7e1997 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -469,6 +469,15 @@ CREATE TABLE ambari.blueprint_configuration (
   config_attributes TEXT,
   PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE ambari.blueprint_setting (
+  id BIGINT NOT NULL,
+  blueprint_name varchar(255) NOT NULL,
+  setting_name varchar(255) NOT NULL,
+  setting_data TEXT NOT NULL, 
+  CONSTRAINT PK_blueprint_setting PRIMARY KEY (id),
+  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES 
ambari.blueprint(blueprint_name));
+
 CREATE TABLE ambari.hostgroup_configuration (
   blueprint_name VARCHAR(255) NOT NULL,
   hostgroup_name VARCHAR(255) NOT NULL,
@@ -481,6 +490,7 @@ GRANT ALL PRIVILEGES ON TABLE ambari.blueprint TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_configuration TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_setting TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_configuration TO :username;
 
 CREATE TABLE ambari.viewmain (
@@ -1172,7 +1182,9 @@ INSERT INTO ambari.ambari_sequences (sequence_name, 
sequence_value)
   union all
   select 'servicecomponentdesiredstate_id_seq', 0
   union all
-  select 'servicecomponent_history_id_seq', 0;
+  select 'servicecomponent_history_id_seq', 0
+  union all
+  select 'blueprint_setting_id_seq', 0;
 
 INSERT INTO ambari.adminresourcetype (resource_type_id, resource_type_name)
   SELECT 1, 'AMBARI'

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index 4bd7a7a..aa8a4d9 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -419,6 +419,15 @@ CREATE TABLE blueprint_configuration (
   config_attributes TEXT,
   PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE blueprint_setting (
+  id NUMERIC(19) NOT NULL,
+  blueprint_name VARCHAR(255) NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_data TEXT NOT NULL,
+  CONSTRAINT PK_blueprint_setting PRIMARY KEY (id),
+  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES 
blueprint(blueprint_name));
+
 CREATE TABLE hostgroup_configuration (
   blueprint_name VARCHAR(255) NOT NULL,
   hostgroup_name VARCHAR(255) NOT NULL,
@@ -1024,6 +1033,7 @@ INSERT INTO ambari_sequences(sequence_name, 
sequence_value) values ('setting_id_
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('hostcomponentstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('servicecomponentdesiredstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('servicecomponent_history_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values 
('blueprint_setting_id_seq', 0);
 
 insert into adminresourcetype (resource_type_id, resource_type_name)
   select 1, 'AMBARI'

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 063db3a..504c910 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -483,6 +483,16 @@ CREATE TABLE blueprint_configuration (
     )
   );
 
+CREATE TABLE blueprint_setting (
+  id BIGINT NOT NULL,
+  blueprint_name VARCHAR(255) NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_data TEXT NOT NULL,
+  CONSTRAINT PK_blueprint_setting PRIMARY KEY (id),
+  CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name),
+  CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES 
blueprint(blueprint_name)
+  );
+
 CREATE TABLE hostgroup_configuration (
   blueprint_name VARCHAR(255) NOT NULL,
   hostgroup_name VARCHAR(255) NOT NULL,
@@ -1137,7 +1147,8 @@ BEGIN TRANSACTION
     ('setting_id_seq', 0),
     ('hostcomponentstate_id_seq', 0),
     ('servicecomponentdesiredstate_id_seq', 0),
-    ('servicecomponent_history_id_seq', 0);
+    ('servicecomponent_history_id_seq', 0),
+    ('blueprint_setting_id_seq', 0);
 
   insert into adminresourcetype (resource_type_id, resource_type_name)
   values

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml 
b/ambari-server/src/main/resources/META-INF/persistence.xml
index 513035f..3eff96f 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -21,6 +21,7 @@
     <class>org.apache.ambari.server.orm.entities.AlertTargetEntity</class>
     <class>org.apache.ambari.server.orm.entities.ArtifactEntity</class>
     <class>org.apache.ambari.server.orm.entities.BlueprintConfigEntity</class>
+    <class>org.apache.ambari.server.orm.entities.BlueprintSettingEntity</class>
     <class>org.apache.ambari.server.orm.entities.BlueprintEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterConfigEntity</class>
     
<class>org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity</class>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/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 01c15f2..2f7fa86 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -358,7 +358,8 @@
         "host_groups/components",
         "host_groups/cardinality",
         "configurations",
-        "validate_topology"
+        "validate_topology",
+        "settings"
     ],
     "Recommendation":[
         "Recommendation/id",

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
index c660d19..279346b 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java
@@ -72,4 +72,15 @@ public class BlueprintEntityTest {
     entity.setConfigurations(configurations);
     assertSame(configurations, entity.getConfigurations());
   }
+
+  /**
+   * Test get and set of Setting object.
+   */
+  @Test
+  public void testSetGetSetting() {
+    BlueprintEntity entity = new BlueprintEntity();
+    Collection<BlueprintSettingEntity> setting = Collections.emptyList();
+    entity.setSettings(setting);
+    assertSame(setting, entity.getSettings());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java
new file mode 100644
index 0000000..507a9111
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+/**
+ * Test all the methods of BlueprintSettingEntity
+ */
+public class BlueprintSettingEntityTest {
+  /**
+   * Verify setSettingName()
+   */
+  @Test
+  public void testSetGetSettingName() {
+    BlueprintSettingEntity entity = new BlueprintSettingEntity();
+    entity.setSettingName("component_settings");
+    assertEquals("component_settings", entity.getSettingName());
+  }
+
+  /**
+   * Verify referencing BlueprintEntity object
+   */
+  @Test
+  public void testSetGetBlueprintEntity() {
+    BlueprintEntity bp = new BlueprintEntity();
+
+    BlueprintSettingEntity entity = new BlueprintSettingEntity();
+    entity.setBlueprintEntity(bp);
+    assertSame(bp, entity.getBlueprintEntity());
+  }
+
+  /**
+   * Verify setBlueprintName()
+   */
+  @Test
+  public void testSetGetBlueprintName() {
+    BlueprintSettingEntity entity = new BlueprintSettingEntity();
+    entity.setBlueprintName("bp2");
+    assertEquals("bp2", entity.getBlueprintName());
+  }
+
+  /**
+   * Verify setSettingData()
+   */
+  @Test
+  public void testSetGetSettingData() {
+    BlueprintSettingEntity entity = new BlueprintSettingEntity();
+    String settingData = 
"[{'recovery_settings':[{'recovery_enabled':'true'}]}]";
+    entity.setSettingData(settingData);
+    assertEquals(settingData, entity.getSettingData());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java
new file mode 100644
index 0000000..e017fb3
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java
@@ -0,0 +1,149 @@
+/**
+ * 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 distribut
+ * ed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.topology;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test the SettingFactory class
+ */
+public class SettingFactoryTest {
+  /**
+   * Test collection of recovery_settings
+   */
+  @Test
+  public void testGetSettingWithSetOfProperties() {
+    SettingFactory settingFactory = new SettingFactory();
+    Map<String, Set<HashMap<String, String>>> properties;
+
+    Setting setting = 
settingFactory.getSetting(createSettingWithSetOfProperties());
+    Set<HashMap<String, String>> propertyValues = 
setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS);
+    assertEquals(propertyValues.size(), 1);
+
+    
assertEquals(propertyValues.iterator().next().get(Setting.SETTING_NAME_RECOVERY_ENABLED),
 "true");
+  }
+
+  /**
+   * Test single recovery_settings at root level
+   */
+  @Test
+  public void testGetSettingWithoutSetOfProperties() {
+    SettingFactory settingFactory = new SettingFactory();
+    Map<String, Set<HashMap<String, String>>> properties;
+
+    Setting setting = 
settingFactory.getSetting(createSettingWithoutSetOfProperties());
+    Set<HashMap<String, String>> propertyValues = 
setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS);
+    assertEquals(propertyValues.size(), 1);
+
+    
assertEquals(propertyValues.iterator().next().get(Setting.SETTING_NAME_RECOVERY_ENABLED),
 "true");
+  }
+
+  /**
+   * {
+   *   "recovery_settings":[
+   *     {
+   *     "recovery_enabled":"true"
+   *     }
+   *   ]
+   * }
+   *
+   * @return
+   */
+  private Collection<Map<String, Object>> createSettingWithSetOfProperties() {
+
+    Set<HashMap<String, String>> setting1 = new HashSet<>();
+    Set<HashMap<String, String>> setting2 = new HashSet<>();
+
+    // Setting 1: Property1
+    HashMap<String, String> setting1Properties1 = new HashMap<>();
+    setting1Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "true");
+    setting1.add(setting1Properties1);
+
+    // Setting 2: Property1 and Property2
+    HashMap<String, String> setting2Properties1 = new HashMap<>();
+    setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS");
+    setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    HashMap<String, String> setting2Properties2 = new HashMap<>();
+    setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ");
+    setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    setting2.add(setting2Properties1);
+    setting2.add(setting2Properties2);
+
+    Collection<Map<String, Object>> setting = new ArrayList<>();
+    Map<String, Object> properties;
+    properties = new HashMap<>();
+    properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS, setting1);
+    setting.add(properties);
+
+    properties = new HashMap<>();
+    properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2);
+    setting.add(properties);
+
+    return setting;
+  }
+
+  /**
+   * {
+   *   "recovery_settings":
+   *     {
+   *     "recovery_enabled":"true"
+   *     }
+   * }
+   *
+   * @return
+   */
+  private Collection<Map<String, Object>> 
createSettingWithoutSetOfProperties() {
+    // Setting 2: Property1 and Property2
+    HashMap<String, String> setting2Properties1 = new HashMap<>();
+    setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS");
+    setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    HashMap<String, String> setting2Properties2 = new HashMap<>();
+    setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ");
+    setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    Set<HashMap<String, String>> setting2 = new HashSet<>();
+    setting2.add(setting2Properties1);
+    setting2.add(setting2Properties2);
+
+    Collection<Map<String, Object>> setting = new ArrayList<>();
+    Map<String, Object> properties;
+    properties = new HashMap<>();
+    properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS + "/" + 
Setting.SETTING_NAME_RECOVERY_ENABLED, "true");
+    setting.add(properties);
+
+    properties = new HashMap<>();
+    properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2);
+    setting.add(properties);
+
+    return setting;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java
new file mode 100644
index 0000000..5615d12
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.topology;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test the Setting class
+ */
+public class SettingTest {
+  /**
+   * Test get and set of entire setting.
+   */
+  @Test
+  public void testGetProperties() {
+    Map<String, Set<HashMap<String, String>>> properties = new HashMap<>();
+    Set<HashMap<String, String>> setting1 = new HashSet<>();
+    Set<HashMap<String, String>> setting2 = new HashSet<>();
+
+    // Setting 1: Property1
+    HashMap<String, String> setting1Properties1 = new HashMap<String, 
String>();
+    setting1Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "true");
+    setting1.add(setting1Properties1);
+
+    // Setting 2: Property1 and Property2
+    HashMap<String, String> setting2Properties1 = new HashMap<String, 
String>();
+    setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS");
+    setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    HashMap<String, String> setting2Properties2 = new HashMap<String, 
String>();
+    setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ");
+    setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    setting2.add(setting2Properties1);
+    setting2.add(setting2Properties2);
+
+    properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS, setting1);
+    properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2);
+
+    Setting setting = new Setting(properties);
+    assertEquals(properties, setting.getProperties());
+  }
+
+  /**
+   * Validate the properties for a given setting.
+   */
+  @Test
+  public void testGetSettingProperties() {
+    Map<String, Set<HashMap<String, String>>> properties = new HashMap<>();
+    Set<HashMap<String, String>> setting1 = new HashSet<>();
+    Set<HashMap<String, String>> setting2 = new HashSet<>();
+
+    // Setting 1: Property1
+    HashMap<String, String> setting1Properties1 = new HashMap<String, 
String>();
+    setting1Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "true");
+    setting1.add(setting1Properties1);
+
+    // Setting 2: Property1 and Property2
+    HashMap<String, String> setting2Properties1 = new HashMap<String, 
String>();
+    setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS");
+    setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    HashMap<String, String> setting2Properties2 = new HashMap<String, 
String>();
+    setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ");
+    setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false");
+
+    setting2.add(setting2Properties1);
+    setting2.add(setting2Properties2);
+
+    properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS, setting1);
+    properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2);
+
+    Setting setting = new Setting(properties);
+    assertEquals(setting2, 
setting.getSettingValue(Setting.SETTING_NAME_SERVICE_SETTINGS));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
index 5cd3bdc..f66f21b 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
@@ -141,7 +141,7 @@ public class UpgradeCatalog240Test {
 
     Capture<List<DBAccessor.DBColumnInfo>> capturedHistoryColumns = 
EasyMock.newCapture();
     dbAccessor.createTable(eq("servicecomponent_history"), 
capture(capturedHistoryColumns),
-        eq((String[]) null));
+            eq((String[]) null));
 
     dbAccessor.addPKConstraint("servicecomponent_history", "PK_sc_history", 
"id");
     dbAccessor.addFKConstraint("servicecomponent_history", 
"FK_sc_history_component_id",
@@ -151,10 +151,10 @@ public class UpgradeCatalog240Test {
         "upgrade", "upgrade_id", false);
 
     dbAccessor.addFKConstraint("servicecomponent_history", 
"FK_sc_history_from_stack_id",
-        "from_stack_id", "stack", "stack_id", false);
+            "from_stack_id", "stack", "stack_id", false);
 
     dbAccessor.addFKConstraint("servicecomponent_history", 
"FK_sc_history_to_stack_id",
-        "to_stack_id", "stack", "stack_id", false);
+            "to_stack_id", "stack", "stack_id", false);
 
 
     expect(dbAccessor.getConnection()).andReturn(connection);
@@ -164,7 +164,7 @@ public class UpgradeCatalog240Test {
     Capture<DBAccessor.DBColumnInfo> capturedClusterUpgradeColumnInfo = 
newCapture();
     dbAccessor.addColumn(eq(UpgradeCatalog240.CLUSTER_TABLE), 
capture(capturedClusterUpgradeColumnInfo));
     dbAccessor.addFKConstraint(UpgradeCatalog240.CLUSTER_TABLE, 
"FK_clusters_upgrade_id",
-        UpgradeCatalog240.CLUSTER_UPGRADE_ID_COLUMN, 
UpgradeCatalog240.UPGRADE_TABLE, "upgrade_id", false);
+            UpgradeCatalog240.CLUSTER_UPGRADE_ID_COLUMN, 
UpgradeCatalog240.UPGRADE_TABLE, "upgrade_id", false);
 
     Capture<DBAccessor.DBColumnInfo> capturedHelpURLColumnInfo = newCapture();
     Capture<DBAccessor.DBColumnInfo> capturedRepeatToleranceColumnInfo = 
newCapture();
@@ -173,6 +173,19 @@ public class UpgradeCatalog240Test {
     dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), 
capture(capturedRepeatToleranceColumnInfo));
     dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), 
capture(capturedRepeatToleranceEnabledColumnInfo));
 
+    // Test creation of blueprint_setting table
+    Capture<List<DBAccessor.DBColumnInfo>> capturedBlueprintSettingColumns = 
EasyMock.newCapture();
+    dbAccessor.createTable(eq(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE), 
capture(capturedBlueprintSettingColumns));
+    dbAccessor.addPKConstraint(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE, 
"PK_blueprint_setting", UpgradeCatalog240.ID);
+    dbAccessor.addUniqueConstraint(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE, 
"UQ_blueprint_setting_name",
+            UpgradeCatalog240.BLUEPRINT_NAME_COL, 
UpgradeCatalog240.SETTING_NAME_COL);
+    dbAccessor.addFKConstraint(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE, 
"FK_blueprint_setting_name",
+            UpgradeCatalog240.BLUEPRINT_NAME_COL, 
UpgradeCatalog240.BLUEPRINT_TABLE,
+            UpgradeCatalog240.BLUEPRINT_NAME_COL, false);
+    expect(dbAccessor.getConnection()).andReturn(connection);
+    expect(connection.createStatement()).andReturn(statement);
+    
expect(statement.executeQuery(anyObject(String.class))).andReturn(resultSet);
+
     replay(dbAccessor, configuration, connection, statement, resultSet);
 
     Module module = new Module() {
@@ -273,6 +286,20 @@ public class UpgradeCatalog240Test {
 
     assertEquals(expectedCaptures, actualCaptures);
 
+    // Verify blueprint_setting columns
+    expectedCaptures = new HashMap<>();
+    expectedCaptures.put(UpgradeCatalog240.ID, Long.class);
+    expectedCaptures.put(UpgradeCatalog240.BLUEPRINT_NAME_COL, String.class);
+    expectedCaptures.put(UpgradeCatalog240.SETTING_NAME_COL, String.class);
+    expectedCaptures.put(UpgradeCatalog240.SETTING_DATA_COL, char[].class);
+
+    actualCaptures = new HashMap<>();
+    for(DBAccessor.DBColumnInfo blueprintSettingsColumnInfo : 
capturedBlueprintSettingColumns.getValue()) {
+      actualCaptures.put(blueprintSettingsColumnInfo.getName(), 
blueprintSettingsColumnInfo.getType());
+    }
+
+    assertEquals(expectedCaptures, actualCaptures);
+
     verify(dbAccessor);
   }
 

Reply via email to