You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by di...@apache.org on 2016/01/11 20:15:41 UTC
[05/13] ambari git commit: AMBARI-12885: Dynamic stack extensions -
install and upgrade support for custom services (tthorpe via dili)
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/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 9cfeffe..0403f46 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
@@ -20,6 +20,7 @@ package org.apache.ambari.server.stack;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.state.stack.ExtensionsXml;
import org.apache.ambari.server.state.stack.RepositoryXml;
import org.apache.ambari.server.state.stack.StackMetainfoXml;
import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
@@ -36,6 +37,7 @@ import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -137,6 +139,11 @@ public class StackDirectory extends StackDefinitionDirectory {
private static final String STACK_METAINFO_FILE_NAME = "metainfo.xml";
/**
+ * extensions file name
+ */
+ private static final String EXTENSIONS_XML_FILE_NAME = "extensions.xml";
+
+ /**
* upgrades directory name
*/
private static final String UPGRADE_PACK_FOLDER_NAME = "upgrades";
@@ -274,7 +281,6 @@ public class StackDirectory extends StackDefinitionDirectory {
*
* @return object representation of the stack role_command_order.json file
*/
-
public StackRoleCommandOrder getRoleCommandOrder() {
return roleCommandOrder;
}
@@ -493,7 +499,7 @@ public class StackDirectory extends StackDefinitionDirectory {
ClassLoader.getSystemResource(ROLE_COMMAND_ORDER_FILE));
}
roleCommandOrder = new StackRoleCommandOrder(result);
- parseRoleCommandOrdersForServices();
+ //parseRoleCommandOrdersForServices();
if (LOG.isDebugEnabled()) {
LOG.debug("Role Command Order for " + rcoFilePath);
roleCommandOrder.printRoleCommandOrder(LOG);
@@ -503,7 +509,7 @@ public class StackDirectory extends StackDefinitionDirectory {
}
}
- private void parseRoleCommandOrdersForServices() {
+ /*private void parseRoleCommandOrdersForServices() {
if (rcoFilePath != null) {
File stack = new File(rcoFilePath).getParentFile();
File servicesDir = new File(stack, "services");
@@ -530,6 +536,6 @@ public class StackDirectory extends StackDefinitionDirectory {
} catch (IOException e) {
LOG.error(String.format("Can not read role command order info %s", rcoFile), e);
}
- }
+ }*/
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/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 2a5e75b..77a37df 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
@@ -22,6 +22,7 @@ import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@@ -30,9 +31,14 @@ import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.dao.ExtensionDAO;
+import org.apache.ambari.server.orm.dao.ExtensionLinkDAO;
import org.apache.ambari.server.orm.dao.MetainfoDAO;
import org.apache.ambari.server.orm.dao.StackDAO;
+import org.apache.ambari.server.orm.entities.ExtensionEntity;
+import org.apache.ambari.server.orm.entities.ExtensionLinkEntity;
import org.apache.ambari.server.orm.entities.StackEntity;
+import org.apache.ambari.server.state.ExtensionInfo;
import org.apache.ambari.server.state.ServiceInfo;
import org.apache.ambari.server.state.StackInfo;
import org.apache.ambari.server.state.stack.OsFamily;
@@ -64,10 +70,24 @@ public class StackManager {
public static final String COMMON_SERVICES = "common-services";
/**
+ * Prefix used for extension services parent path string
+ */
+ public static final String EXTENSIONS = "extensions";
+
+ /**
+ * extensions file name
+ */
+ public static final String EXTENSIONS_XML_FILE_NAME = "extensions.xml";
+
+ public static final String METAINFO_FILE_NAME = "metainfo.xml";
+
+ /**
* Provides access to non-stack server functionality
*/
private StackContext stackContext;
+ private File stackRoot;
+
/**
* Logger
*/
@@ -79,12 +99,19 @@ public class StackManager {
private Map<String, StackInfo> stackMap = new HashMap<String, StackInfo>();
/**
+ * Map of extension id to extension info
+ */
+ private Map<String, ExtensionInfo> extensionMap = new HashMap<String, ExtensionInfo>();
+
+ /**
* Constructor. Initialize stack manager.
*
* @param stackRoot
* stack root directory
* @param commonServicesRoot
* common services root directory
+ * @param extensionRoot
+ * extensions root directory
* @param osFamily
* the OS family read from resources
* @param metaInfoDAO
@@ -93,6 +120,10 @@ public class StackManager {
* action meta data automatically injected
* @param stackDao
* stack DAO automatically injected
+ * @param extensionDao
+ * extension DAO automatically injected
+ * @param linkDao
+ * extension link DAO automatically injected
*
* @throws AmbariException
* if an exception occurs while processing the stacks
@@ -100,29 +131,60 @@ public class StackManager {
@Inject
public StackManager(@Assisted("stackRoot") File stackRoot,
@Assisted("commonServicesRoot") @Nullable File commonServicesRoot,
+ @Assisted("extensionRoot") @Nullable File extensionRoot,
@Assisted OsFamily osFamily, MetainfoDAO metaInfoDAO,
- ActionMetadata actionMetadata, StackDAO stackDao)
+ ActionMetadata actionMetadata, StackDAO stackDao, ExtensionDAO extensionDao,
+ ExtensionLinkDAO linkDao)
throws AmbariException {
LOG.info("Initializing the stack manager...");
validateStackDirectory(stackRoot);
validateCommonServicesDirectory(commonServicesRoot);
+ validateExtensionDirectory(extensionRoot);
+ this.stackRoot = stackRoot;
stackMap = new HashMap<String, StackInfo>();
stackContext = new StackContext(metaInfoDAO, actionMetadata, osFamily);
+ extensionMap = new HashMap<String, ExtensionInfo>();
+
Map<String, ServiceModule> commonServiceModules = parseCommonServicesDirectory(commonServicesRoot);
Map<String, StackModule> stackModules = parseStackDirectory(stackRoot);
+ Map<String, ExtensionModule> extensionModules = parseExtensionDirectory(extensionRoot);
+
+ //Read the extension links from the DB
+ for (StackModule module : stackModules.values()) {
+ StackInfo stack = module.getModuleInfo();
+ List<ExtensionLinkEntity> entities = linkDao.findByStack(stack.getName(), stack.getVersion());
+ for (ExtensionLinkEntity entity : entities) {
+ String name = entity.getExtension().getExtensionName();
+ String version = entity.getExtension().getExtensionVersion();
+ String key = name + StackManager.PATH_DELIMITER + version;
+ ExtensionModule extensionModule = extensionModules.get(key);
+ if (extensionModule != null) {
+ //Add the extension to the stack
+ module.getExtensionModules().put(key, extensionModule);
+ //linkStackToExtension(stack, extension);
+ }
+ }
+ }
+
+ fullyResolveCommonServices(stackModules, commonServiceModules, extensionModules);
+ fullyResolveExtensions(stackModules, commonServiceModules, extensionModules);
+ fullyResolveStacks(stackModules, commonServiceModules, extensionModules);
+
+ populateDB(stackDao, extensionDao);
+
+ }
- fullyResolveCommonServices(stackModules, commonServiceModules);
- fullyResolveStacks(stackModules, commonServiceModules);
+ private void populateDB(StackDAO stackDao, ExtensionDAO extensionDao) throws AmbariException {
// for every stack read in, ensure that we have a database entry for it;
// don't put try/catch logic around this since a failure here will
// cause other things to break down the road
Collection<StackInfo> stacks = getStacks();
- for( StackInfo stack : stacks ){
+ for(StackInfo stack : stacks ){
String stackName = stack.getName();
String stackVersion = stack.getVersion();
@@ -136,6 +198,101 @@ public class StackManager {
stackDao.create(stackEntity);
}
}
+
+ // for every extension read in, ensure that we have a database entry for it;
+ // don't put try/catch logic around this since a failure here will
+ // cause other things to break down the road
+ Collection<ExtensionInfo> extensions = getExtensions();
+ for(ExtensionInfo extension : extensions ){
+ String extensionName = extension.getName();
+ String extensionVersion = extension.getVersion();
+
+ if (extensionDao.find(extensionName, extensionVersion) == null) {
+ LOG.info("Adding extension {}-{} to the database", extensionName, extensionVersion);
+
+ ExtensionEntity extensionEntity = new ExtensionEntity();
+ extensionEntity.setExtensionName(extensionName);
+ extensionEntity.setExtensionVersion(extensionVersion);
+
+ extensionDao.create(extensionEntity);
+ }
+ }
+
+ }
+
+ public void unlinkStackFromExtension(StackInfo stack, ExtensionInfo extension) throws AmbariException {
+ /*File stackVersionDir = new File(new File(stackRoot, stack.getName()), stack.getVersion());
+ File servicesDir = new File(stackVersionDir, "services");
+
+ for (ServiceInfo service : extension.getServices()) {
+ String name = service.getName();
+ File serviceDir = new File(servicesDir, name);
+ if (serviceDir.exists() && !serviceDir.isFile()) {
+ File xmlFile = new File(serviceDir, METAINFO_FILE_NAME);
+ if (xmlFile.exists())
+ xmlFile.delete();
+ serviceDir.delete();
+ }
+ }*/
+
+ }
+
+ /*private void writeServiceMetainfoXmlFile(ServiceMetainfoXml serviceXml, File file) throws AmbariException {
+ PrintWriter writer = null;
+ try {
+ writer = new PrintWriter(file);
+ writer.println("<?xml version=\"1.0\"?>");
+ writer.println("<metainfo>");
+ writer.println(" <schemaVersion>2.0</schemaVersion>");
+ writer.println(" <services>");
+ for (ServiceInfo service : serviceXml.getServices()) {
+ writer.println(" <service>");
+ writer.println(" <name>" + service.getName() + "</name>");
+ writer.println(" <extends>" + service.getParent() + "</extends>");
+ writer.println(" </service>");
+ }
+ writer.println(" </services>");
+ writer.println("</metainfo>");
+
+ writer.flush();
+ }
+ catch (Exception e) {
+ throw new AmbariException("Unable to create service metainfo file for extension service: " + file.getAbsolutePath(), e);
+ }
+ finally {
+ writer.close();
+ }
+ }*/
+
+ public void linkStackToExtension(StackInfo stack, ExtensionInfo extension) throws AmbariException {
+ /*File stackVersionDir = new File(new File(stackRoot, stack.getName()), stack.getVersion());
+ File servicesDir = new File(stackVersionDir, "services");
+
+ for (ServiceInfo service : extension.getServices()) {
+ String name = service.getName();
+ File serviceDir = new File(servicesDir, name);
+ if (serviceDir.exists() && serviceDir.isFile())
+ throw new AmbariException("Unable to create service directory for extension service: " + serviceDir.getAbsolutePath());
+ if (!serviceDir.exists())
+ serviceDir.mkdir();
+ if (!serviceDir.exists())
+ throw new AmbariException("Unable to create service directory for extension service: " + serviceDir.getAbsolutePath());
+
+ ServiceInfo stackService = new ServiceInfo();
+ stackService.setName(name);
+ String parent = StackManager.EXTENSIONS + PATH_DELIMITER + extension.getName()
+ + PATH_DELIMITER + extension.getVersion() + PATH_DELIMITER + name;
+ stackService.setParent(parent);
+
+ ServiceMetainfoXml serviceXML = new ServiceMetainfoXml();
+ List<ServiceInfo> services = new ArrayList<ServiceInfo>();
+ services.add(stackService);
+ serviceXML.setServices(services);
+
+ File xmlFile = new File(serviceDir, METAINFO_FILE_NAME);
+ writeServiceMetainfoXmlFile(serviceXML, xmlFile);
+ }*/
+
}
/**
@@ -177,6 +334,44 @@ public class StackManager {
}
/**
+ * Obtain the extension info specified by name and version.
+ *
+ * @param name name of the extension
+ * @param version version of the extension
+ * @return The extension corresponding to the specified name and version.
+ * If no matching stack exists, null is returned.
+ */
+ public ExtensionInfo getExtension(String name, String version) {
+ return extensionMap.get(name + StackManager.PATH_DELIMITER + version);
+ }
+
+ /**
+ * Obtain all extensions for the given name.
+ *
+ * @param name extension name
+ * @return A collection of all extensions with the given name.
+ * If no extensions match the specified name, an empty collection is returned.
+ */
+ public Collection<ExtensionInfo> getExtensions(String name) {
+ Collection<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+ for (ExtensionInfo extension: extensionMap.values()) {
+ if (extension.getName().equals(name)) {
+ extensions.add(extension);
+ }
+ }
+ return extensions;
+ }
+
+ /**
+ * Obtain all extensions.
+ *
+ * @return collection of all extensions
+ */
+ public Collection<ExtensionInfo> getExtensions() {
+ return extensionMap.values();
+ }
+
+ /**
* Determine if all tasks which update stack repo urls have completed.
*
* @return true if all of the repo update tasks have completed; false otherwise
@@ -193,12 +388,12 @@ public class StackManager {
* @throws AmbariException if unable to resolve all stacks
*/
private void fullyResolveStacks(
- Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules)
+ Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules, Map<String, ExtensionModule> extensions)
throws AmbariException {
// Resolve all stacks without finalizing the stacks.
for (StackModule stack : stackModules.values()) {
if (stack.getModuleState() == ModuleState.INIT) {
- stack.resolve(null, stackModules, commonServiceModules);
+ stack.resolve(null, stackModules, commonServiceModules, extensions);
}
}
// Finalize the common services and stacks to remove sub-modules marked for deletion.
@@ -208,6 +403,9 @@ public class StackManager {
for(ServiceModule commonService : commonServiceModules.values()) {
commonService.finalizeModule();
}
+ for (ExtensionModule extension : extensions.values()) {
+ extension.finalizeModule();
+ }
for (StackModule stack : stackModules.values()) {
stack.finalizeModule();
}
@@ -223,11 +421,29 @@ public class StackManager {
* @throws AmbariException if unable to resolve all common services
*/
private void fullyResolveCommonServices(
- Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules)
+ Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules, Map<String, ExtensionModule> extensions)
throws AmbariException {
for(ServiceModule commonService : commonServiceModules.values()) {
if (commonService.getModuleState() == ModuleState.INIT) {
- commonService.resolveCommonService(stackModules, commonServiceModules);
+ commonService.resolveCommonService(stackModules, commonServiceModules, extensions);
+ }
+ }
+ }
+
+ /**
+ * Fully resolve extensions.
+ *
+ * @param extensionModules map of extension id which contains name and version to extension module.
+ * @param stackModules map of stack id which contains name and version to stack module.
+ * @param commonServiceModules map of common service id which contains name and version to common service module.
+ * @throws AmbariException if unable to resolve all extensions
+ */
+ private void fullyResolveExtensions(Map<String, StackModule> stackModules, Map<String, ServiceModule> commonServiceModules,
+ Map<String, ExtensionModule> extensionModules)
+ throws AmbariException {
+ for(ExtensionModule extensionModule : extensionModules.values()) {
+ if (extensionModule.getModuleState() == ModuleState.INIT) {
+ extensionModule.resolve(null, stackModules, commonServiceModules, extensionModules);
}
}
}
@@ -279,6 +495,34 @@ public class StackManager {
}
}
+
+
+ /**
+ * Validate that the specified extension root is a valid directory.
+ *
+ * @param extensionRoot the extension root directory to validate
+ * @throws AmbariException if the specified extension root directory is invalid
+ */
+ private void validateExtensionDirectory(File extensionRoot) throws AmbariException {
+ LOG.info("Validating extension directory {} ...", extensionRoot);
+
+ if (extensionRoot == null)
+ return;
+
+ String extensionRootAbsPath = extensionRoot.getAbsolutePath();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loading extension information"
+ + ", extensionRoot = " + extensionRootAbsPath);
+ }
+
+ //For backwards compatibility extension directory may not exist
+ if (extensionRoot.exists() && !extensionRoot.isDirectory()) {
+ throw new AmbariException("" + Configuration.METADATA_DIR_PATH
+ + " should be a directory"
+ + ", extensionRoot = " + extensionRootAbsPath);
+ }
+ }
+
/**
* Parse the specified common services root directory
*
@@ -357,4 +601,42 @@ public class StackManager {
}
return stackModules;
}
+
+ /**
+ * Parse the specified extension root directory
+ *
+ * @param extensionRoot the extension root directory to parse
+ * @return map of extension id which contains name and version to extension module.
+ * @throws AmbariException if unable to parse all extensions
+ */
+ private Map<String, ExtensionModule> parseExtensionDirectory(File extensionRoot) throws AmbariException {
+ Map<String, ExtensionModule> extensionModules = new HashMap<String, ExtensionModule>();
+ if (extensionRoot == null || !extensionRoot.exists())
+ return extensionModules;
+
+ File[] extensionFiles = extensionRoot.listFiles(AmbariMetaInfo.FILENAME_FILTER);
+ for (File extensionNameFolder : extensionFiles) {
+ if (extensionNameFolder.isFile()) {
+ continue;
+ }
+ for (File extensionVersionFolder : extensionNameFolder.listFiles(AmbariMetaInfo.FILENAME_FILTER)) {
+ if (extensionVersionFolder.isFile()) {
+ continue;
+ }
+ String extensionName = extensionNameFolder.getName();
+ String extensionVersion = extensionVersionFolder.getName();
+
+ ExtensionModule extensionModule = new ExtensionModule(new ExtensionDirectory(extensionVersionFolder.getPath()), stackContext);
+ String extensionKey = extensionName + StackManager.PATH_DELIMITER + extensionVersion;
+ extensionModules.put(extensionKey, extensionModule);
+ extensionMap.put(extensionKey, extensionModule.getModuleInfo());
+ }
+ }
+
+ if (stackMap.isEmpty()) {
+ throw new AmbariException("Unable to find extension definitions under " +
+ "extensionRoot = " + extensionRoot.getAbsolutePath());
+ }
+ return extensionModules;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManagerFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManagerFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManagerFactory.java
index 5aa2b5f..d672546 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManagerFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManagerFactory.java
@@ -38,11 +38,14 @@ public interface StackManagerFactory {
* @param commonServicesRoot
* the root of the common services from which other stack services
* are extended (not {@code null}).
+ * @param extensionRoot
+ * the root of the extensions (not {@code null}).
* @param osFamily
* the list of all parsed OS families (not {@code null}).
* @return a stack manager instance which contains all parsed stacks.
*/
StackManager create(@Assisted("stackRoot") File stackRoot,
@Nullable @Assisted("commonServicesRoot") File commonServicesRoot,
+ @Assisted("extensionRoot") @Nullable File extensionRoot,
OsFamily osFamily);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/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 def33f0..e54867b 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
@@ -29,6 +29,7 @@ import java.util.Set;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.ExtensionInfo;
import org.apache.ambari.server.state.PropertyDependencyInfo;
import org.apache.ambari.server.state.PropertyInfo;
import org.apache.ambari.server.state.RepositoryInfo;
@@ -93,6 +94,11 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
private Map<String, ServiceModule> serviceModules = new HashMap<String, ServiceModule>();
/**
+ * Map of linked extension modules keyed by extension name + version
+ */
+ private Map<String, ExtensionModule> extensionModules = new HashMap<String, ExtensionModule>();
+
+ /**
* Corresponding StackInfo instance
*/
private StackInfo stackInfo;
@@ -129,6 +135,14 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
populateStackInfo();
}
+ public Map<String, ServiceModule> getServiceModules() {
+ return serviceModules;
+ }
+
+ public Map<String, ExtensionModule> getExtensionModules() {
+ return extensionModules;
+ }
+
/**
* Fully resolve the stack. See stack resolution description in the class documentation.
* If the stack has a parent, this stack will be merged against its fully resolved parent
@@ -146,14 +160,25 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
*/
@Override
public void resolve(
- StackModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+ StackModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
moduleState = ModuleState.VISITED;
String parentVersion = stackInfo.getParentStackVersion();
- mergeServicesWithExplicitParent(allStacks, commonServices);
+ mergeServicesWithExplicitParent(allStacks, commonServices, extensions);
+ addExtensionServices();
+
// merge with parent version of same stack definition
if (parentVersion != null) {
- mergeStackWithParent(parentVersion, allStacks, commonServices);
+ mergeStackWithParent(parentVersion, allStacks, commonServices, extensions);
+ }
+ for (ExtensionInfo extension : stackInfo.getExtensions()) {
+ String extensionKey = extension.getName() + StackManager.PATH_DELIMITER + extension.getVersion();
+ ExtensionModule extensionModule = extensions.get(extensionKey);
+ if (extensionModule == null) {
+ throw new AmbariException("Extension '" + stackInfo.getName() + ":" + stackInfo.getVersion() +
+ "' specifies an extension " + extensionKey + " that doesn't exist");
+ }
+ mergeStackWithExtension(extensionModule, allStacks, commonServices, extensions);
}
processRepositories();
processPropertyDependencies();
@@ -179,6 +204,12 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
public void finalizeModule() {
finalizeChildModules(serviceModules.values());
finalizeChildModules(configurationModules.values());
+
+ // This needs to be merged during the finalize to avoid the RCO from services being inherited by the children stacks
+ // The RCOs from a service should only be inherited through the service.
+ for (ServiceModule module : serviceModules.values()) {
+ mergeRoleCommandOrder(module);
+ }
}
/**
@@ -200,7 +231,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
* @throws AmbariException if an exception occurs merging with the parent
*/
private void mergeStackWithParent(
- String parentVersion, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+ String parentVersion, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
String parentStackKey = stackInfo.getName() + StackManager.PATH_DELIMITER + parentVersion;
@@ -211,8 +242,8 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
"' specifies a parent that doesn't exist");
}
- resolveStack(parentStack, allStacks, commonServices);
- mergeConfigurations(parentStack, allStacks, commonServices);
+ resolveStack(parentStack, allStacks, commonServices, extensions);
+ mergeConfigurations(parentStack, allStacks, commonServices, extensions);
mergeRoleCommandOrder(parentStack);
if (stackInfo.getStackHooksFolder() == null) {
@@ -228,7 +259,33 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
stackInfo.setWidgetsDescriptorFileLocation(parentStack.getModuleInfo().getWidgetsDescriptorFileLocation());
}
- mergeServicesWithParent(parentStack, allStacks, commonServices);
+ mergeServicesWithParent(parentStack, allStacks, commonServices, extensions);
+ }
+
+ /**
+ * Merge the stack one of its linked extensions.
+ *
+ * @param allStacks all stacks in stack definition
+ * @param commonServices all common services specified in the stack definition
+ * @param parentVersion version of the stacks parent
+ *
+ * @throws AmbariException if an exception occurs merging with the parent
+ */
+ private void mergeStackWithExtension(
+ ExtensionModule extension, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
+ throws AmbariException {
+
+ //mergeConfigurations(extension, allStacks, commonServices, extensions);
+ //mergeRoleCommandOrder(extension);
+
+ // grab stack level kerberos.json from parent stack
+ /*if (stackInfo.getKerberosDescriptorFileLocation() == null) {
+ stackInfo.setKerberosDescriptorFileLocation(extension.getModuleInfo().getKerberosDescriptorFileLocation());
+ }
+
+ if (stackInfo.getWidgetsDescriptorFileLocation() == null) {
+ stackInfo.setWidgetsDescriptorFileLocation(parentStack.getModuleInfo().getWidgetsDescriptorFileLocation());
+ }*/
}
/**
@@ -241,11 +298,11 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
* @throws AmbariException if an exception occurs merging the child services with the parent stack
*/
private void mergeServicesWithParent(
- StackModule parentStack, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+ StackModule parentStack, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
stackInfo.getServices().clear();
Collection<ServiceModule> mergedModules = mergeChildModules(
- allStacks, commonServices, serviceModules, parentStack.serviceModules);
+ allStacks, commonServices, extensions, serviceModules, parentStack.serviceModules);
for (ServiceModule module : mergedModules) {
serviceModules.put(module.getId(), module);
stackInfo.getServices().add(module.getModuleInfo());
@@ -260,12 +317,12 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
* @throws AmbariException if an exception occurs while merging child services with their explicit parents
*/
private void mergeServicesWithExplicitParent(
- Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) throws AmbariException {
+ Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions) throws AmbariException {
for (ServiceModule service : serviceModules.values()) {
ServiceInfo serviceInfo = service.getModuleInfo();
String parent = serviceInfo.getParent();
if (parent != null) {
- mergeServiceWithExplicitParent(service, parent, allStacks, commonServices);
+ mergeServiceWithExplicitParent(service, parent, allStacks, commonServices, extensions);
}
}
}
@@ -281,12 +338,14 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
*/
private void mergeServiceWithExplicitParent(
ServiceModule service, String parent, Map<String, StackModule> allStacks,
- Map<String, ServiceModule> commonServices)
+ Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
if(isCommonServiceParent(parent)) {
- mergeServiceWithCommonServiceParent(service, parent, allStacks,commonServices);
+ mergeServiceWithCommonServiceParent(service, parent, allStacks, commonServices, extensions);
+ } else if(isExtensionServiceParent(parent)) {
+ mergeServiceWithExtensionServiceParent(service, parent, allStacks, commonServices, extensions);
} else {
- mergeServiceWithStackServiceParent(service, parent, allStacks, commonServices);
+ mergeServiceWithStackServiceParent(service, parent, allStacks, commonServices, extensions);
}
}
@@ -302,6 +361,25 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
}
/**
+ * Check if parent is extension service
+ * @param parent Parent string
+ * @return true: if parent is extension service, false otherwise
+ */
+ private boolean isExtensionServiceParent(String parent) {
+ return parent != null
+ && !parent.isEmpty()
+ && parent.split(StackManager.PATH_DELIMITER)[0].equalsIgnoreCase(StackManager.EXTENSIONS);
+ }
+
+ private void addExtensionServices() throws AmbariException {
+ for (ExtensionModule extension : extensionModules.values()) {
+ stackInfo.getExtensions().add(extension.getModuleInfo());
+ Collection<ServiceModule> services = extension.getServiceModules().values();
+ addServices(services);
+ }
+ }
+
+ /**
* Merge a service with its explicitly specified common service as parent.
* Parent: common-services/<serviceName>/<serviceVersion>
* Common Services Lookup Key: <serviceName>/<serviceVersion>
@@ -317,7 +395,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
*/
private void mergeServiceWithCommonServiceParent(
ServiceModule service, String parent, Map<String, StackModule> allStacks,
- Map<String, ServiceModule> commonServices)
+ Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
ServiceInfo serviceInfo = service.getModuleInfo();
String[] parentToks = parent.split(StackManager.PATH_DELIMITER);
@@ -337,7 +415,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
stackInfo.setErrors(error);
} else {
if (baseService.isValid()) {
- service.resolve(baseService, allStacks, commonServices);
+ service.resolve(baseService, allStacks, commonServices, extensions);
} else {
setValid(false);
stackInfo.setValid(false);
@@ -348,6 +426,62 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
}
/**
+ * Merge a service with its explicitly specified extension service as parent.
+ * Parent: extensions/<extensionName>/<extensionVersion>/<serviceName>
+ * Example:
+ * Parent: extensions/EXT_TEST/1.0/CUSTOM_SERVICE
+ *
+ * @param service the service to merge
+ * @param parent the explicitly specified extension as parent
+ * @param allStacks all stacks specified in the stack definition
+ * @param commonServices all common services
+ * @param extensions all extensions
+ * @throws AmbariException
+ */
+ private void mergeServiceWithExtensionServiceParent(
+ ServiceModule service, String parent, Map<String, StackModule> allStacks,
+ Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
+ throws AmbariException {
+ ServiceInfo serviceInfo = service.getModuleInfo();
+ String[] parentToks = parent.split(StackManager.PATH_DELIMITER);
+ if(parentToks.length != 4 || !parentToks[0].equalsIgnoreCase(StackManager.EXTENSIONS)) {
+ throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+ + stackInfo.getVersion() + "' extends an invalid parent: '" + parent + "'");
+ }
+
+ String extensionKey = parentToks[1] + StackManager.PATH_DELIMITER + parentToks[2];
+ ExtensionModule extension = extensions.get(extensionKey);
+
+ if (extension == null || !extension.isValid()) {
+ setInvalid(extension, "The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+ + stackInfo.getVersion() + "' extends a non-existent service: '" + parent + "'");
+ } else {
+ resolveExtension(extension, allStacks, commonServices, extensions);
+ ServiceModule parentService = extension.getServiceModules().get(parentToks[3]);
+ if (parentService == null || !parentService.isValid()) {
+ setInvalid(parentService, "The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+ + stackInfo.getVersion() + "' extends a non-existent service: '" + parent + "'");
+ }
+ else
+ service.resolve(parentService, allStacks, commonServices, extensions);
+ }
+ }
+
+ private void setInvalid(Validable module, String error) {
+ setValid(false);
+ stackInfo.setValid(false);
+ if (module == null) {
+ setErrors(error);
+ stackInfo.setErrors(error);
+ }
+ else {
+ setErrors(module.getErrors());
+ stackInfo.setErrors(module.getErrors());
+ }
+ }
+
+
+ /**
* Merge a service with its explicitly specified stack service as parent.
* Parent: <stackName>/<stackVersion>/<serviceName>
* Stack Lookup Key: <stackName>/<stackVersion>
@@ -358,16 +492,17 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
* @param service the service to merge
* @param parent the explicitly specified stack service as parent
* @param allStacks all stacks specified in the stack definition
- * @param commonServices all common services specified in the stack definition
+ * @param commonServices all common services
+ * @param extensions all extensions
* @throws AmbariException
*/
private void mergeServiceWithStackServiceParent(
ServiceModule service, String parent, Map<String, StackModule> allStacks,
- Map<String, ServiceModule> commonServices)
+ Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
ServiceInfo serviceInfo = service.getModuleInfo();
String[] parentToks = parent.split(StackManager.PATH_DELIMITER);
- if(parentToks.length != 3 || parentToks[0].equalsIgnoreCase(StackManager.COMMON_SERVICES)) {
+ if(parentToks.length != 3 || parentToks[0].equalsIgnoreCase(StackManager.EXTENSIONS) || parentToks[0].equalsIgnoreCase(StackManager.COMMON_SERVICES)) {
throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+ stackInfo.getVersion() + "' extends an invalid parent: '" + parent + "'");
}
@@ -376,17 +511,17 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
StackModule baseStack = allStacks.get(baseStackKey);
if (baseStack == null) {
throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
- + stackInfo.getVersion() + "' extends a service in a non-existent stack: '" + baseStackKey + "'");
+ + stackInfo.getVersion() + "' extends a service in a non-existent extension: '" + baseStackKey + "'");
}
- resolveStack(baseStack, allStacks, commonServices);
+ resolveStack(baseStack, allStacks, commonServices, extensions);
ServiceModule baseService = baseStack.serviceModules.get(parentToks[2]);
if (baseService == null) {
throw new AmbariException("The service '" + serviceInfo.getName() + "' in stack '" + stackInfo.getName() + ":"
+ stackInfo.getVersion() + "' extends a non-existent service: '" + parent + "'");
}
- service.resolve(baseService, allStacks, commonServices);
+ service.resolve(baseService, allStacks, commonServices, extensions);
}
/**
@@ -402,8 +537,7 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
+ ", stackName = " + stackInfo.getName()
+ ", stackVersion = " + stackInfo.getVersion());
-
- //odo: give additional thought on handling missing metainfo.xml
+ //todo: give additional thought on handling missing metainfo.xml
StackMetainfoXml smx = stackDirectory.getMetaInfoFile();
if (smx != null) {
if (!smx.isValid()) {
@@ -522,13 +656,13 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
* @param commonServices all common services specified in the stack definition
*/
private void mergeConfigurations(
- StackModule parent, Map<String,StackModule> allStacks, Map<String, ServiceModule> commonServices)
+ StackModule parent, Map<String,StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
stackInfo.getProperties().clear();
stackInfo.setAllConfigAttributes(new HashMap<String, Map<String, Map<String, String>>>());
Collection<ConfigurationModule> mergedModules = mergeChildModules(
- allStacks, commonServices, configurationModules, parent.configurationModules);
+ allStacks, commonServices, extensions, configurationModules, parent.configurationModules);
for (ConfigurationModule module : mergedModules) {
configurationModules.put(module.getId(), module);
stackInfo.getProperties().addAll(module.getModuleInfo().getProperties());
@@ -545,10 +679,10 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
* @throws AmbariException if unable to resolve the stack
*/
private void resolveStack(
- StackModule stackToBeResolved, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
+ StackModule stackToBeResolved, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
throws AmbariException {
if (stackToBeResolved.getModuleState() == ModuleState.INIT) {
- stackToBeResolved.resolve(null, allStacks, commonServices);
+ stackToBeResolved.resolve(null, allStacks, commonServices, extensions);
} else if (stackToBeResolved.getModuleState() == ModuleState.VISITED) {
//todo: provide more information to user about cycle
throw new AmbariException("Cycle detected while parsing stack definition");
@@ -562,6 +696,29 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
}
/**
+ * Resolve an extension module.
+ *
+ * @param extension extension module to be resolved
+ * @param allStacks all stack modules in stack definition
+ * @param commonServices all common services
+ * @param extensions all extensions
+ * @throws AmbariException if unable to resolve the stack
+ */
+ private void resolveExtension(
+ ExtensionModule extension, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions)
+ throws AmbariException {
+ if (extension.getModuleState() == ModuleState.INIT) {
+ extension.resolve(null, allStacks, commonServices, extensions);
+ } else if (extension.getModuleState() == ModuleState.VISITED) {
+ //todo: provide more information to user about cycle
+ throw new AmbariException("Cycle detected while parsing extension definition");
+ }
+ if (!extension.isValid() || (extension.getModuleInfo() != null && !extension.getModuleInfo().isValid())) {
+ setInvalid(extension, null);
+ }
+ }
+
+ /**
* Add a child service module to the stack.
*
* @param service service module to add
@@ -714,11 +871,47 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
*
* @param parentStack parent stack
*/
-
private void mergeRoleCommandOrder(StackModule parentStack) {
-
stackInfo.getRoleCommandOrder().merge(parentStack.stackInfo.getRoleCommandOrder());
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Role Command Order for " + stackInfo.getName() + "-" + stackInfo.getVersion() +
+ " parent " + stackInfo.getParentStackVersion());
+ stackInfo.getRoleCommandOrder().printRoleCommandOrder(LOG);
+ }
+ }
+ /**
+ * Merge role command order with the extension
+ *
+ * @param extension linked extension
+ */
+ private void mergeRoleCommandOrder(ExtensionModule extension) {
+ if (extension.getModuleInfo().getRoleCommandOrder() == null)
+ return;
+
+ stackInfo.getRoleCommandOrder().merge(extension.getModuleInfo().getRoleCommandOrder(), true);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Role Command Order for " + stackInfo.getName() + "-" + stackInfo.getVersion() +
+ " extension " + extension.getId());
+ stackInfo.getRoleCommandOrder().printRoleCommandOrder(LOG);
+ }
+ }
+
+ /**
+ * Merge role command order with the service
+ *
+ * @param service service
+ */
+ private void mergeRoleCommandOrder(ServiceModule service) {
+ if (service.getModuleInfo().getRoleCommandOrder() == null)
+ return;
+
+ stackInfo.getRoleCommandOrder().merge(service.getModuleInfo().getRoleCommandOrder(), true);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Role Command Order for " + stackInfo.getName() + "-" + stackInfo.getVersion() +
+ " service " + service.getModuleInfo().getName());
+ stackInfo.getRoleCommandOrder().printRoleCommandOrder(LOG);
+ }
}
@Override
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/stack/StackServiceDirectory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackServiceDirectory.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackServiceDirectory.java
index d27e52a..e27d556 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackServiceDirectory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackServiceDirectory.java
@@ -47,14 +47,13 @@ public class StackServiceDirectory extends ServiceDirectory {
@Override
/**
- * Parse stack service directory.
+ * Calculate the package directory for the stack service.
* packageDir Format: stacks/<stackName>/<stackVersion>/services/<serviceName>/package
* Example:
* directory: "/var/lib/ambari-server/resources/stacks/HDP/2.0.6/services/HDFS"
* packageDir: "stacks/HDP/2.0.6/services/HDFS/package"
- * @throws AmbariException if unable to parse the service directory
*/
- protected void parsePath() throws AmbariException {
+ protected void calculatePackageDir() {
File serviceDir = new File(getAbsolutePath());
File stackVersionDir = serviceDir.getParentFile().getParentFile();
File stackDir = stackVersionDir.getParentFile();
@@ -78,6 +77,6 @@ public class StackServiceDirectory extends ServiceDirectory {
LOG.debug(String.format("Service package folder %s for service %s for stack %s does not exist.",
absPackageDir, serviceDir.getName(), stackId));
}
- parseMetaInfoFile();
+ //parseMetaInfoFile();
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/stack/ThemeModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ThemeModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ThemeModule.java
index 85ce252..b0089c1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ThemeModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ThemeModule.java
@@ -82,7 +82,8 @@ public class ThemeModule extends BaseModule<ThemeModule, ThemeInfo> implements V
}
@Override
- public void resolve(ThemeModule parent, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices) throws AmbariException {
+ public void resolve(ThemeModule parent, Map<String, StackModule> allStacks,
+ Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions) throws AmbariException {
ThemeInfo parentModuleInfo = parent.getModuleInfo();
if (parent.getModuleInfo() != null && !moduleInfo.isDeleted()) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
index 2c5c5af..92fc152 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
@@ -27,8 +27,11 @@ import java.util.concurrent.locks.ReadWriteLock;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.controller.ClusterResponse;
import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
+import org.apache.ambari.server.orm.entities.ClusterExtensionVersionEntity;
import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
+import org.apache.ambari.server.orm.entities.ExtensionRepositoryVersionEntity;
import org.apache.ambari.server.orm.entities.HostEntity;
+import org.apache.ambari.server.orm.entities.HostExtensionVersionEntity;
import org.apache.ambari.server.orm.entities.HostVersionEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
@@ -136,6 +139,12 @@ public interface Cluster {
Collection<ClusterVersionEntity> getAllClusterVersions();
/**
+ * Get all of the ClusterExtensionVersionEntity objects for the cluster and extension.
+ * @return
+ */
+ Collection<ClusterExtensionVersionEntity> getAllClusterExtensionVersions(String extensionName);
+
+ /**
* Get desired stack version
* @return
*/
@@ -216,6 +225,20 @@ public interface Cluster {
throws AmbariException;
/**
+ * For a given host, will either either update an existing Extension Host Version Entity for the given version, or create
+ * one if it doesn't exist
+ *
+ * @param host Host Entity object
+ * @param repositoryVersion Extension Repository Version that the host is transitioning to
+ * @param extensionId extension information with the version
+ * @return Returns either the newly created or the updated Extension Host Version Entity.
+ * @throws AmbariException
+ */
+ HostExtensionVersionEntity transitionHostExtensionVersionState(HostEntity host,
+ final ExtensionRepositoryVersionEntity repositoryVersion, final ExtensionId extensionId)
+ throws AmbariException;
+
+ /**
* Update state of a cluster stack version for cluster based on states of host versions and stackids.
* @param repositoryVersion the repository version entity whose version is a value like 2.2.1.0-100)
* @throws AmbariException
@@ -223,6 +246,13 @@ public interface Cluster {
void recalculateClusterVersionState(RepositoryVersionEntity repositoryVersion) throws AmbariException;
/**
+ * Update state of a cluster extension version for cluster based on states of host extension versions and extension ids.
+ * @param repositoryVersion the extension repository version entity whose version is a value like 2.2.1.0-1000)
+ * @throws AmbariException
+ */
+ void recalculateClusterExtensionVersionState(ExtensionRepositoryVersionEntity repositoryVersion) throws AmbariException;
+
+ /**
* Update state of all cluster stack versions for cluster based on states of host versions.
* @throws AmbariException
*/
@@ -262,6 +292,20 @@ public interface Cluster {
RepositoryVersionState state) throws AmbariException;
/**
+ * Transition an existing cluster version from one state to another.
+ *
+ * @param extensionId
+ * Extension ID
+ * @param version
+ * Extension version
+ * @param state
+ * Desired state
+ * @throws AmbariException
+ */
+ void transitionClusterExtensionVersion(ExtensionId extensionId, String version,
+ RepositoryVersionState state) throws AmbariException;
+
+ /**
* Gets whether the cluster is still initializing or has finished with its
* deployment requests.
*
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
index fd68060..18f456d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
@@ -46,6 +46,19 @@ public class ComponentInfo {
@XmlElements(@XmlElement(name = "versionAdvertised"))
private boolean versionAdvertised = false;
+ @XmlElements(@XmlElement(name = "notPreferableOnServerComponents"))
+ private boolean notPreferableOnServerComponents = false;
+
+ @XmlElements(@XmlElement(name = "notValuable"))
+ private boolean notValuable = false;
+
+ @XmlElements(@XmlElement(name = "useCardinalityForLayout"))
+ private boolean useCardinalityForLayout = false;
+
+ private String layout = null;
+
+ private int idealMinimum = 1;
+
/**
* Added at schema ver 2
*/
@@ -104,6 +117,11 @@ public class ComponentInfo {
deleted = prototype.deleted;
cardinality = prototype.cardinality;
versionAdvertised = prototype.versionAdvertised;
+ notPreferableOnServerComponents = prototype.notPreferableOnServerComponents;
+ notValuable = prototype.notValuable;
+ useCardinalityForLayout = prototype.useCardinalityForLayout;
+ layout = prototype.layout;
+ idealMinimum = prototype.idealMinimum;
clientsToUpdateConfigs = prototype.clientsToUpdateConfigs;
commandScript = prototype.commandScript;
customCommands = prototype.customCommands;
@@ -247,6 +265,46 @@ public class ComponentInfo {
return versionAdvertised;
}
+ public boolean isNotPreferableOnServerComponents() {
+ return notPreferableOnServerComponents;
+ }
+
+ public void setNotPreferableOnServerComponents(boolean notPreferableOnServerComponents) {
+ this.notPreferableOnServerComponents = notPreferableOnServerComponents;
+ }
+
+ public boolean isNotValuable() {
+ return notValuable;
+ }
+
+ public void setNotValuable(boolean notValuable) {
+ this.notValuable = notValuable;
+ }
+
+ public boolean isUseCardinalityForLayout() {
+ return useCardinalityForLayout;
+ }
+
+ public void setUseCardinalityForLayout(boolean useCardinalityForLayout) {
+ this.useCardinalityForLayout = useCardinalityForLayout;
+ }
+
+ public String getLayout() {
+ return layout;
+ }
+
+ public void setLayout(String layout) {
+ this.layout = layout;
+ }
+
+ public int getIdealMinimum() {
+ return idealMinimum;
+ }
+
+ public void setIdealMinimum(int idealMinimum) {
+ this.idealMinimum = idealMinimum;
+ }
+
public List<String> getClientsToUpdateConfigs() {
return clientsToUpdateConfigs;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java
new file mode 100644
index 0000000..401244a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java
@@ -0,0 +1,155 @@
+/**
+ * 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.state;
+
+import org.apache.ambari.server.orm.entities.ExtensionEntity;
+import org.apache.ambari.server.utils.VersionUtils;
+
+public class ExtensionId implements Comparable<ExtensionId> {
+
+ private static final String NAME_SEPARATOR = "-";
+
+ private String extensionName;
+ private String extensionVersion;
+
+ public ExtensionId() {
+ extensionName = "";
+ extensionVersion = "";
+ }
+
+ public ExtensionId(String extensionId) {
+ parseExtensionIdHelper(this, extensionId);
+ }
+
+ public ExtensionId(ExtensionInfo extension) {
+ extensionName = extension.getName();
+ extensionVersion = extension.getVersion();
+ }
+
+ public ExtensionId(String extensionName, String extensionVersion) {
+ this(extensionName + NAME_SEPARATOR + extensionVersion);
+ }
+
+ public ExtensionId(ExtensionEntity entity) {
+ this(entity.getExtensionName(), entity.getExtensionVersion());
+ }
+
+ /**
+ * @return the extensionName
+ */
+ public String getExtensionName() {
+ return extensionName;
+ }
+
+ /**
+ * @return the extensionVersion
+ */
+ public String getExtensionVersion() {
+ return extensionVersion;
+ }
+
+ /**
+ * @return the extensionVersion
+ */
+ public String getExtensionId() {
+ if (extensionName.isEmpty()
+ && extensionVersion.isEmpty()) {
+ return "";
+ }
+ return extensionName + NAME_SEPARATOR + extensionVersion;
+ }
+
+ /**
+ * @param extensionId the extensionVersion to set
+ */
+ public void setExtensionId(String extensionId) {
+ parseExtensionIdHelper(this, extensionId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof ExtensionId)) {
+ return false;
+ }
+ if (this == object) {
+ return true;
+ }
+ ExtensionId s = (ExtensionId) object;
+ return extensionName.equals(s.extensionName) && extensionVersion.equals(s.extensionVersion);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ int result = extensionName != null ? extensionName.hashCode() : 0;
+ result = 31 * result + (extensionVersion != null ? extensionVersion.hashCode() : 0);
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(ExtensionId other) {
+ if (this == other) {
+ return 0;
+ }
+
+ if (other == null) {
+ throw new RuntimeException("Cannot compare with a null value.");
+ }
+
+ int returnValue = getExtensionName().compareTo(other.getExtensionName());
+ if (returnValue == 0) {
+ returnValue = VersionUtils.compareVersions(getExtensionVersion(), other.getExtensionVersion());
+ } else {
+ throw new RuntimeException("ExtensionId with different names cannot be compared.");
+ }
+ return returnValue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getExtensionId();
+ }
+
+ private void parseExtensionIdHelper(ExtensionId extensionVersion, String extensionId) {
+ if (extensionId == null || extensionId.isEmpty()) {
+ extensionVersion.extensionName = "";
+ extensionVersion.extensionVersion = "";
+ return;
+ }
+
+ int pos = extensionId.indexOf('-');
+ if (pos == -1 || (extensionId.length() <= (pos + 1))) {
+ throw new RuntimeException("Could not parse invalid Extension Id" + ", extensionId=" + extensionId);
+ }
+
+ extensionVersion.extensionName = extensionId.substring(0, pos);
+ extensionVersion.extensionVersion = extensionId.substring(pos + 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java
new file mode 100644
index 0000000..b07fb2f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java
@@ -0,0 +1,414 @@
+/**
+ * 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.state;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.ExtensionVersionResponse;
+import org.apache.ambari.server.stack.Validable;
+import org.apache.ambari.server.state.stack.ExtensionMetainfoXml;
+import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
+import org.apache.ambari.server.state.stack.UpgradePack;
+
+public class ExtensionInfo implements Comparable<ExtensionInfo>, Validable{
+ private String name;
+ private String version;
+ private String rcoFileLocation;
+ private String kerberosDescriptorFileLocation;
+ private String widgetsDescriptorFileLocation;
+ private String mainRepoId;
+ private List<RepositoryInfo> repositories;
+ private Collection<ServiceInfo> services;
+ private String parentExtensionVersion;
+
+ private List<ExtensionMetainfoXml.Stack> stacks;
+ private List<ExtensionMetainfoXml.Extension> extensions;
+ private List<PropertyInfo> properties;
+ 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);
+ }
+
+ //private String stackHooksFolder;
+
+ private String upgradesFolder = null;
+
+ private volatile Map<String, PropertyInfo> requiredProperties;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getMainRepositoryId() {
+ if (mainRepoId != null)
+ return mainRepoId;
+ else
+ // if main repo id is not defined in repository then
+ // try main repo as a combination of extension name and version
+ return (name + "-" + version);
+ }
+
+ public void setMainRepositoryId(String repoid) {
+ this.mainRepoId = repoid;
+ }
+
+ public List<RepositoryInfo> getRepositories() {
+ if( repositories == null ) repositories = new ArrayList<RepositoryInfo>();
+ return repositories;
+ }
+
+ public void setRepositories(List<RepositoryInfo> repositories) {
+ this.repositories = repositories;
+ }
+
+ public synchronized Collection<ServiceInfo> getServices() {
+ if (services == null) services = new ArrayList<ServiceInfo>();
+ return services;
+ }
+
+ public ServiceInfo getService(String name) {
+ Collection<ServiceInfo> services = getServices();
+ for (ServiceInfo service : services) {
+ if (service.getName().equals(name)) {
+ return service;
+ }
+ }
+ //todo: exception?
+ return null;
+ }
+
+ public synchronized void setServices(Collection<ServiceInfo> services) {
+ this.services = services;
+ }
+
+ public List<PropertyInfo> getProperties() {
+ if (properties == null) properties = new ArrayList<PropertyInfo>();
+ return properties;
+ }
+
+ public void setProperties(List<PropertyInfo> properties) {
+ this.properties = properties;
+ }
+
+ /**
+ * Obtain the config types associated with this stack.
+ * The returned map is an unmodifiable view.
+ * @return copy of the map of config types associated with this stack
+ */
+ public synchronized Map<String, Map<String, Map<String, String>>> getConfigTypeAttributes() {
+ return configTypes == null ?
+ Collections.<String, Map<String, Map<String, String>>>emptyMap() :
+ Collections.unmodifiableMap(configTypes);
+ }
+
+
+ /**
+ * Add the given type and set it's attributes.
+ *
+ * @param type configuration type
+ * @param typeAttributes attributes associated with the type
+ */
+ /*public synchronized void setConfigTypeAttributes(String type, Map<String, Map<String, String>> typeAttributes) {
+ if (this.configTypes == null) {
+ configTypes = new HashMap<String, Map<String, Map<String, String>>>();
+ }
+ // todo: no exclusion mechanism for stack config types
+ configTypes.put(type, typeAttributes);
+ }*/
+
+ /**
+ * Set all types and associated attributes. Any previously existing types and
+ * attributes are removed prior to setting the new values.
+ *
+ * @param types map of type attributes
+ */
+ /*public synchronized void setAllConfigAttributes(Map<String, Map<String, Map<String, String>>> types) {
+ configTypes = new HashMap<String, Map<String, Map<String, String>>>();
+ for (Map.Entry<String, Map<String, Map<String, String>>> entry : types.entrySet()) {
+ setConfigTypeAttributes(entry.getKey(), entry.getValue());
+ }
+ }*/
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Stack name:" + name + "\nversion:" +
+ version + " \nvalid:" + isValid());
+ if (services != null) {
+ sb.append("\n\t\tService:");
+ for (ServiceInfo service : services) {
+ sb.append("\t\t");
+ sb.append(service);
+ }
+ }
+
+ if (repositories != null) {
+ sb.append("\n\t\tRepositories:");
+ for (RepositoryInfo repository : repositories) {
+ sb.append("\t\t");
+ sb.append(repository.toString());
+ }
+ }
+
+ return sb.toString();
+ }
+
+
+ @Override
+ public int hashCode() {
+ return 31 + name.hashCode() + version.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ExtensionInfo)) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ ExtensionInfo stackInfo = (ExtensionInfo) obj;
+ return getName().equals(stackInfo.getName()) && getVersion().equals(stackInfo.getVersion());
+ }
+
+ public ExtensionVersionResponse convertToResponse() {
+
+ // Get the stack-level Kerberos descriptor file path
+ String stackDescriptorFileFilePath = getKerberosDescriptorFileLocation();
+
+ String widgetDescriptorFilePath = getWidgetsDescriptorFileLocation();
+
+ // Collect the services' Kerberos descriptor files
+ Collection<ServiceInfo> serviceInfos = getServices();
+ // The collection of service descriptor files. A Set is being used because some Kerberos descriptor
+ // files contain multiple services, therefore the same File may be encountered more than once.
+ // For example the YARN directory may contain YARN and MAPREDUCE2 services.
+ Collection<File> serviceDescriptorFiles = new HashSet<File>();
+ if (serviceInfos != null) {
+ for (ServiceInfo serviceInfo : serviceInfos) {
+ File file = serviceInfo.getKerberosDescriptorFile();
+ if (file != null) {
+ serviceDescriptorFiles.add(file);
+ }
+ }
+ }
+
+ /*return new ExtensionVersionResponse(getVersion(), getMinUpgradeVersion(),
+ isActive(), getParentStackVersion(), getConfigTypeAttributes(),
+ (stackDescriptorFileFilePath == null) ? null : new File(stackDescriptorFileFilePath),
+ serviceDescriptorFiles,
+ null == upgradePacks ? Collections.<String>emptySet() : upgradePacks.keySet(),
+ isValid(), getErrors());*/
+
+ return new ExtensionVersionResponse(getVersion(), getParentExtensionVersion(), getConfigTypeAttributes(),
+ (stackDescriptorFileFilePath == null) ? null : new File(stackDescriptorFileFilePath),
+ serviceDescriptorFiles,
+ null == upgradePacks ? Collections.<String>emptySet() : upgradePacks.keySet(),
+ isValid(), getErrors());
+ }
+
+ /*public String getMinUpgradeVersion() {
+ return minUpgradeVersion;
+ }
+
+ public void setMinUpgradeVersion(String minUpgradeVersion) {
+ this.minUpgradeVersion = minUpgradeVersion;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }*/
+
+ public String getParentExtensionVersion() {
+ return parentExtensionVersion;
+ }
+
+ public void setParentExtensionVersion(String parentExtensionVersion) {
+ this.parentExtensionVersion = parentExtensionVersion;
+ }
+
+ public StackRoleCommandOrder getRoleCommandOrder() {
+ return roleCommandOrder;
+ }
+
+ public void setRoleCommandOrder(StackRoleCommandOrder roleCommandOrder) {
+ this.roleCommandOrder = roleCommandOrder;
+ }
+
+ public String getRcoFileLocation() {
+ return rcoFileLocation;
+ }
+
+ public void setRcoFileLocation(String rcoFileLocation) {
+ this.rcoFileLocation = rcoFileLocation;
+ }
+
+ public String getKerberosDescriptorFileLocation() {
+ return kerberosDescriptorFileLocation;
+ }
+
+ public void setKerberosDescriptorFileLocation(String kerberosDescriptorFileLocation) {
+ this.kerberosDescriptorFileLocation = kerberosDescriptorFileLocation;
+ }
+
+ public String getWidgetsDescriptorFileLocation() {
+ return widgetsDescriptorFileLocation;
+ }
+
+ public void setWidgetsDescriptorFileLocation(String widgetsDescriptorFileLocation) {
+ this.widgetsDescriptorFileLocation = widgetsDescriptorFileLocation;
+ }
+
+ /**
+ * Set the path of the stack upgrade directory.
+ *
+ * @param path the path to the upgrades directory
+ */
+ public void setUpgradesFolder(String path) {
+ upgradesFolder = path;
+ }
+
+ /**
+ * Obtain the path of the upgrades folder or null if directory doesn't exist.
+ *
+ * @return the upgrades folder, or {@code null} if not set
+ */
+ public String getUpgradesFolder() {
+ return upgradesFolder;
+ }
+
+ /**
+ * Set upgrade packs.
+ *
+ * @param upgradePacks map of upgrade packs
+ */
+ public void setUpgradePacks(Map<String, UpgradePack> upgradePacks) {
+ this.upgradePacks = upgradePacks;
+ }
+
+ /**
+ * Obtain all stack upgrade packs.
+ *
+ * @return map of upgrade pack name to upgrade pack or {@code null} of no packs
+ */
+ public Map<String, UpgradePack> getUpgradePacks() {
+ return upgradePacks;
+ }
+
+
+ @Override
+ public int compareTo(ExtensionInfo o) {
+ String myId = name + "-" + version;
+ String oId = o.name + "-" + o.version;
+ return myId.compareTo(oId);
+ }
+
+ public List<ExtensionMetainfoXml.Stack> getStacks() {
+ return stacks;
+ }
+
+ public void setStacks(List<ExtensionMetainfoXml.Stack> stacks) {
+ this.stacks = stacks;
+ }
+
+ public List<ExtensionMetainfoXml.Extension> getExtensions() {
+ return extensions;
+ }
+
+ public void setExtensions(List<ExtensionMetainfoXml.Extension> extensions) {
+ this.extensions = extensions;
+ }
+
+ //todo: ensure that required properties are never modified...
+ /*public Map<String, PropertyInfo> getRequiredProperties() {
+ Map<String, PropertyInfo> result = requiredProperties;
+ if (result == null) {
+ synchronized(this) {
+ result = requiredProperties;
+ if (result == null) {
+ requiredProperties = result = new HashMap<String, PropertyInfo>();
+ List<PropertyInfo> properties = getProperties();
+ for (PropertyInfo propertyInfo : properties) {
+ if (propertyInfo.isRequireInput()) {
+ result.put(propertyInfo.getName(), propertyInfo);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }*/
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyDependencyInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyDependencyInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyDependencyInfo.java
index a801311..f6759d1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyDependencyInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyDependencyInfo.java
@@ -82,9 +82,5 @@ public class PropertyDependencyInfo {
'}';
}
- public StackConfigurationDependencyResponse convertToResponse() {
- return new StackConfigurationDependencyResponse(getName(), getType());
- }
-
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
index f1e8d62..1296aad 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.controller.ServiceComponentHostResponse;
+import org.apache.ambari.server.orm.entities.ExtensionRepositoryVersionEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
@@ -40,6 +41,11 @@ public interface ServiceComponentHost {
public String getClusterName();
/**
+ * Returns whether or not the service to which this object maps comes from an extension
+ */
+ public boolean isExtensionService();
+
+ /**
* Get the Service this object maps to
* @return Name of the Service
*/
@@ -220,4 +226,11 @@ public interface ServiceComponentHost {
*/
public RepositoryVersionEntity recalculateHostVersionState() throws AmbariException;
+ /**
+ * Changes extension host version state according to state of the components installed on the host.
+ * @return The Extension Repository Version Entity with that component in the host
+ * @throws AmbariException if host is detached from the cluster
+ */
+ public ExtensionRepositoryVersionEntity recalculateHostExtensionVersionState() throws AmbariException;
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/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 a58cda3..ab09905 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
@@ -27,6 +27,7 @@ import com.google.common.collect.Multimaps;
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.apache.ambari.server.state.stack.StackRoleCommandOrder;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonFilter;
@@ -67,6 +68,7 @@ public class ServiceInfo implements Validable{
private String version;
private String comment;
private String serviceType;
+ boolean extensionService = false;
@XmlTransient
private List<PropertyInfo> properties;
@@ -138,6 +140,8 @@ public class ServiceInfo implements Validable{
@XmlTransient
private File widgetsDescriptorFile = null;
+
+ private StackRoleCommandOrder roleCommandOrder;
@XmlTransient
private boolean valid = true;
@@ -683,6 +687,14 @@ public String getVersion() {
this.widgetsDescriptorFile = widgetsDescriptorFile;
}
+ public StackRoleCommandOrder getRoleCommandOrder() {
+ return roleCommandOrder;
+ }
+
+ public void setRoleCommandOrder(StackRoleCommandOrder roleCommandOrder) {
+ this.roleCommandOrder = roleCommandOrder;
+ }
+
/**
* @return config types this service contains configuration for, but which are primarily related to another service
*/
@@ -769,6 +781,13 @@ public String getVersion() {
this.themesMap = themesMap;
}
+ public boolean isExtensionService() {
+ return extensionService;
+ }
+
+ public void setExtensionService(boolean extensionService) {
+ this.extensionService = extensionService;
+ }
public List<ServicePropertyInfo> getServicePropertyList() {
return servicePropertyList;
http://git-wip-us.apache.org/repos/asf/ambari/blob/647929db/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 0d87b68..42ac622 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
@@ -63,6 +63,7 @@ public class StackInfo implements Comparable<StackInfo>, Validable{
private String widgetsDescriptorFileLocation;
private List<RepositoryInfo> repositories;
private Collection<ServiceInfo> services;
+ private Collection<ExtensionInfo> extensions;
private String parentStackVersion;
// stack-level properties
private List<PropertyInfo> properties;
@@ -164,6 +165,34 @@ public class StackInfo implements Comparable<StackInfo>, Validable{
this.services = services;
}
+ public synchronized Collection<ExtensionInfo> getExtensions() {
+ if (extensions == null) extensions = new ArrayList<ExtensionInfo>();
+ return extensions;
+ }
+
+ public ExtensionInfo getExtension(String name) {
+ Collection<ExtensionInfo> extensions = getExtensions();
+ for (ExtensionInfo extension : extensions) {
+ if (extension.getName().equals(name)) {
+ return extension;
+ }
+ }
+ //todo: exception?
+ return null;
+ }
+
+ public ExtensionInfo getExtensionByService(String serviceName) {
+ Collection<ExtensionInfo> extensions = getExtensions();
+ for (ExtensionInfo extension : extensions) {
+ for (ServiceInfo service : services) {
+ if (service.getName().equals(serviceName))
+ return extension;
+ }
+ }
+ //todo: exception?
+ return null;
+ }
+
public List<PropertyInfo> getProperties() {
if (properties == null) properties = new ArrayList<PropertyInfo>();
return properties;