You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2016/06/20 21:34:45 UTC
[3/6] ambari git commit: AMBARI-12885. Dynamic stack extensions -
install and upgrade support for custom services (Tim Thorpe via alejandro)
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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..b17da30
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java
@@ -0,0 +1,160 @@
+/**
+ * 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;
+
+/**
+ * An extension version is like a stack version but it contains custom services. Linking an extension
+ * version to the current stack version allows the cluster to install the custom services contained in
+ * the extension version.
+ */
+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/300a7e21/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..89a6fb5
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java
@@ -0,0 +1,208 @@
+/**
+ * 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;
+
+/**
+ * An extension version is like a stack version but it contains custom services. Linking an extension
+ * version to the current stack version allows the cluster to install the custom services contained in
+ * the extension version.
+ */
+public class ExtensionInfo implements Comparable<ExtensionInfo>, Validable{
+ private String name;
+ private String version;
+ private Collection<ServiceInfo> services;
+ private String parentExtensionVersion;
+
+ private List<ExtensionMetainfoXml.Stack> stacks;
+ private List<ExtensionMetainfoXml.Extension> extensions;
+ 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 addError(String error) {
+ errorSet.add(error);
+ }
+
+ @Override
+ public Collection<String> getErrors() {
+ return errorSet;
+ }
+
+ @Override
+ public void addErrors(Collection<String> errors) {
+ this.errorSet.addAll(errors);
+ }
+
+ //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 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;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Extension 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);
+ }
+ }
+
+ 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 extInfo = (ExtensionInfo) obj;
+ return getName().equals(extInfo.getName()) && getVersion().equals(extInfo.getVersion());
+ }
+
+ public ExtensionVersionResponse convertToResponse() {
+ 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(), getParentExtensionVersion(),
+ isValid(), getErrors());
+ }
+
+ public String getParentExtensionVersion() {
+ return parentExtensionVersion;
+ }
+
+ public void setParentExtensionVersion(String parentExtensionVersion) {
+ this.parentExtensionVersion = parentExtensionVersion;
+ }
+
+ @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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 76840ea..6fda8bc 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;
@@ -145,6 +146,8 @@ public class ServiceInfo implements Validable{
@XmlTransient
private File widgetsDescriptorFile = null;
+ private StackRoleCommandOrder roleCommandOrder;
+
@XmlTransient
private boolean valid = true;
@@ -730,6 +733,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
*/
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 c7738cd..c30f28f 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
@@ -49,6 +49,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;
@@ -161,6 +162,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;
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java
new file mode 100644
index 0000000..790e514
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java
@@ -0,0 +1,204 @@
+/**
+ * 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.stack;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.ambari.server.stack.Validable;
+
+/**
+ * Represents the extension <code>metainfo.xml</code> file.
+ *
+ * An extension version is like a stack version but it contains custom services. Linking an extension
+ * version to the current stack version allows the cluster to install the custom services contained in
+ * the extension version.
+ */
+@XmlRootElement(name="metainfo")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ExtensionMetainfoXml implements Validable{
+
+ @XmlElement(name="extends")
+ private String extendsVersion = null;
+
+ @XmlElement(name="versions")
+ private Version version = new Version();
+
+ @XmlElement(name="prerequisites")
+ private Prerequisites prerequisites = new Prerequisites();
+
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class Prerequisites {
+ private Prerequisites() {
+ }
+ @XmlElementWrapper(name="min-stack-versions")
+ @XmlElements(@XmlElement(name="stack"))
+ private List<Stack> stacks = new ArrayList<Stack>();
+
+ @XmlElementWrapper(name="min-extension-versions")
+ @XmlElements(@XmlElement(name="extension"))
+ private List<Extension> extensions = new ArrayList<Extension>();
+
+ public List<Stack> getStacks() {
+ return stacks;
+ }
+
+ public List<Extension> getExtensions() {
+ return extensions;
+ }
+ }
+
+ @XmlTransient
+ private boolean valid = true;
+
+ /**
+ *
+ * @return valid xml flag
+ */
+ @Override
+ public boolean isValid() {
+ return valid;
+ }
+
+ /**
+ *
+ * @param valid set validity flag
+ */
+ @Override
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+
+ @XmlTransient
+ private Set<String> errorSet = new HashSet<String>();
+
+ @Override
+ public void addError(String error) {
+ errorSet.add(error);
+ }
+
+ @Override
+ public Collection<String> getErrors() {
+ return errorSet;
+ }
+
+ @Override
+ public void addErrors(Collection<String> errors) {
+ this.errorSet.addAll(errors);
+ }
+
+ /**
+ * @return the parent stack version number
+ */
+ public String getExtends() {
+ return extendsVersion;
+ }
+
+ /**
+ * @return gets the version
+ */
+ public Version getVersion() {
+ return version;
+ }
+
+ public List<Stack> getStacks() {
+ return prerequisites.getStacks();
+ }
+
+ public List<Extension> getExtensions() {
+ return prerequisites.getExtensions();
+ }
+
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class Version {
+ private Version() {
+ }
+ private boolean active = false;
+ private String upgrade = null;
+
+ /**
+ * @return <code>true</code> if the stack is active
+ */
+ public boolean isActive() {
+ return active;
+ }
+
+ /**
+ * @return the upgrade version number, if set
+ */
+ public String getUpgrade() {
+ return upgrade;
+ }
+ }
+
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class Stack {
+ private Stack() {
+ }
+ private String name = null;
+ private String version = null;
+
+ /**
+ * @return the stack name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the stack version, this may be something like 1.0.*
+ */
+ public String getVersion() {
+ return version;
+ }
+ }
+
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class Extension {
+ private Extension() {
+ }
+ private String name = null;
+ private String version = null;
+
+ /**
+ * @return the extension name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the extension version, this may be something like 1.0.*
+ */
+ public String getVersion() {
+ return version;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
index 418c389..1fa6dcf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java
@@ -86,6 +86,10 @@ public class ServiceMetainfoXml implements Validable{
public List<ServiceInfo> getServices() {
return services;
}
+
+ public void setServices(List<ServiceInfo> services) {
+ this.services = services;
+ }
public String getSchemaVersion() {
return schemaVersion;
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 81b5653..bee0942 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
@@ -161,7 +161,6 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
protected static final String PHOENIX_QUERY_SERVER_PRINCIPAL_KEY = "phoenix.queryserver.kerberos.principal";
protected static final String PHOENIX_QUERY_SERVER_KEYTAB_KEY = "phoenix.queryserver.keytab.file";
-
private static final String OOZIE_ENV_CONFIG = "oozie-env";
private static final String HIVE_ENV_CONFIG = "hive-env";
private static final String AMS_SITE = "ams-site";
@@ -174,6 +173,10 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
protected static final String HBASE_SITE_CONFIG = "hbase-site";
protected static final String HBASE_SPNEGO_PRINCIPAL_KEY = "hbase.security.authentication.spnego.kerberos.principal";
protected static final String HBASE_SPNEGO_KEYTAB_KEY = "hbase.security.authentication.spnego.kerberos.keytab";
+ protected static final String EXTENSION_TABLE = "extension";
+ protected static final String EXTENSION_ID_COLUMN = "extension_id";
+ protected static final String EXTENSION_LINK_TABLE = "extensionlink";
+ protected static final String EXTENSION_LINK_ID_COLUMN = "link_id";
private static final Map<String, Integer> ROLE_ORDER;
@@ -265,6 +268,8 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
protected void executeDDLUpdates() throws AmbariException, SQLException {
updateAdminPermissionTable();
updateServiceComponentDesiredStateTable();
+ createExtensionTable();
+ createExtensionLinkTable();
createSettingTable();
updateRepoVersionTableDDL();
updateServiceComponentDesiredStateTableDDL();
@@ -292,7 +297,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
columns.add(new DBColumnInfo("username", String.class, 255, null, false));
columns.add(new DBColumnInfo("password", String.class, 255, null, false));
dbAccessor.createTable(REMOTE_AMBARI_CLUSTER_TABLE, columns, CLUSTER_ID);
- dbAccessor.addUniqueConstraint(REMOTE_AMBARI_CLUSTER_TABLE , "unq_remote_ambari_cluster" , CLUSTER_NAME);
+ dbAccessor.addUniqueConstraint(REMOTE_AMBARI_CLUSTER_TABLE , "UQ_remote_ambari_cluster" , CLUSTER_NAME);
addSequence("remote_cluster_id_seq", 1L, false);
List<DBColumnInfo> remoteClusterServiceColumns = new ArrayList<>();
@@ -465,6 +470,48 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
}
}
+ private void createExtensionTable() throws SQLException {
+ List<DBColumnInfo> columns = new ArrayList<>();
+
+ // Add extension table
+ LOG.info("Creating " + EXTENSION_TABLE + " table");
+
+ columns.add(new DBColumnInfo(EXTENSION_ID_COLUMN, Long.class, null, null, false));
+ columns.add(new DBColumnInfo("extension_name", String.class, 255, null, false));
+ columns.add(new DBColumnInfo("extension_version", String.class, 255, null, false));
+ dbAccessor.createTable(EXTENSION_TABLE, columns, EXTENSION_ID_COLUMN);
+
+ // create UNIQUE constraint, ensuring column order matches SQL files
+ String[] uniqueColumns = new String[] { "extension_name", "extension_version" };
+ dbAccessor.addUniqueConstraint(EXTENSION_TABLE, "UQ_extension", uniqueColumns);
+
+ addSequence("extension_id_seq", 0L, false);
+ }
+
+ private void createExtensionLinkTable() throws SQLException {
+ List<DBColumnInfo> columns = new ArrayList<>();
+
+ // Add extension link table
+ LOG.info("Creating " + EXTENSION_LINK_TABLE + " table");
+
+ columns.add(new DBColumnInfo(EXTENSION_LINK_ID_COLUMN, Long.class, null, null, false));
+ columns.add(new DBColumnInfo("stack_id", Long.class, null, null, false));
+ columns.add(new DBColumnInfo(EXTENSION_ID_COLUMN, Long.class, null, null, false));
+ dbAccessor.createTable(EXTENSION_LINK_TABLE, columns, EXTENSION_LINK_ID_COLUMN);
+
+ // create UNIQUE constraint, ensuring column order matches SQL files
+ String[] uniqueColumns = new String[] { "stack_id", EXTENSION_ID_COLUMN };
+ dbAccessor.addUniqueConstraint(EXTENSION_LINK_TABLE, "UQ_extension_link", uniqueColumns);
+
+ dbAccessor.addFKConstraint(EXTENSION_LINK_TABLE, "FK_extensionlink_extension_id",
+ EXTENSION_ID_COLUMN, EXTENSION_TABLE, EXTENSION_ID_COLUMN, false);
+
+ dbAccessor.addFKConstraint(EXTENSION_LINK_TABLE, "FK_extensionlink_stack_id",
+ "stack_id", STACK_TABLE, "stack_id", false);
+
+ addSequence("link_id_seq", 0L, false);
+ }
+
private void createSettingTable() throws SQLException {
List<DBColumnInfo> columns = new ArrayList<>();
@@ -1429,7 +1476,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
// create UNIQUE constraint, ensuring column order matches SQL files
String[] uniqueColumns = new String[] { "component_name", "service_name", "cluster_id" };
- dbAccessor.addUniqueConstraint(SERVICE_COMPONENT_DS_TABLE, "unq_scdesiredstate_name",
+ dbAccessor.addUniqueConstraint(SERVICE_COMPONENT_DS_TABLE, "UQ_scdesiredstate_name",
uniqueColumns);
// add FKs back to SCDS in both HCDS and HCS tables
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 257ca42..aa8a39e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -22,7 +22,23 @@ CREATE TABLE stack(
stack_name VARCHAR(255) NOT NULL,
stack_version VARCHAR(255) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version));
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version));
+
+CREATE TABLE extension(
+ extension_id BIGINT NOT NULL,
+ extension_name VARCHAR(255) NOT NULL,
+ extension_version VARCHAR(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY (extension_id),
+ CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version));
+
+CREATE TABLE extensionlink(
+ link_id BIGINT NOT NULL,
+ stack_id BIGINT NOT NULL,
+ extension_id BIGINT NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY (link_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id),
+ CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id));
CREATE TABLE adminresourcetype (
resource_type_id INTEGER NOT NULL,
@@ -176,7 +192,7 @@ CREATE TABLE servicecomponentdesiredstate (
service_name VARCHAR(255) NOT NULL,
recovery_enabled SMALLINT NOT NULL DEFAULT 0,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id));
@@ -789,7 +805,7 @@ CREATE TABLE remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name));
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name));
CREATE TABLE remoteambariclusterservice(
id BIGINT NOT NULL,
@@ -1092,6 +1108,10 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
union all
select 'stack_id_seq', 0 FROM SYSIBM.SYSDUMMY1
union all
+ select 'extension_id_seq', 0 FROM SYSIBM.SYSDUMMY1
+ union all
+ select 'link_id_seq', 0 FROM SYSIBM.SYSDUMMY1
+ union all
select 'topology_host_info_id_seq', 0 FROM SYSIBM.SYSDUMMY1
union all
select 'topology_host_request_id_seq', 0 FROM SYSIBM.SYSDUMMY1
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 9b68174..3be1299 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -32,7 +32,23 @@ CREATE TABLE stack(
stack_name VARCHAR(100) NOT NULL,
stack_version VARCHAR(100) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version));
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version));
+
+CREATE TABLE extension(
+ extension_id BIGINT NOT NULL,
+ extension_name VARCHAR(255) NOT NULL,
+ extension_version VARCHAR(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY (extension_id),
+ CONSTRAINT UQ_extension UNIQUE (extension_name, extension_version));
+
+CREATE TABLE extensionlink(
+ link_id BIGINT NOT NULL,
+ stack_id BIGINT NOT NULL,
+ extension_id BIGINT NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY (link_id),
+ CONSTRAINT UQ_extension_link UNIQUE (stack_id, extension_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id));
CREATE TABLE adminresourcetype (
resource_type_id INTEGER NOT NULL,
@@ -176,7 +192,7 @@ CREATE TABLE servicecomponentdesiredstate (
service_name VARCHAR(100) NOT NULL,
recovery_enabled SMALLINT NOT NULL DEFAULT 0,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id));
@@ -796,7 +812,7 @@ CREATE TABLE remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name));
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name));
CREATE TABLE remoteambariclusterservice(
id BIGINT NOT NULL,
@@ -1061,6 +1077,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES
('upgrade_group_id_seq', 0),
('upgrade_item_id_seq', 0),
('stack_id_seq', 0),
+ ('extension_id_seq', 0),
+ ('link_id_seq', 0),
('widget_id_seq', 0),
('widget_layout_id_seq', 0),
('topology_host_info_id_seq', 0),
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 362c714..6bbb282 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -22,7 +22,23 @@ CREATE TABLE stack(
stack_name VARCHAR2(255) NOT NULL,
stack_version VARCHAR2(255) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version));
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version));
+
+CREATE TABLE extension(
+ extension_id NUMERIC(19) NOT NULL,
+ extension_name VARCHAR2(255) NOT NULL,
+ extension_version VARCHAR2(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY (extension_id),
+ CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version));
+
+CREATE TABLE extensionlink(
+ link_id NUMERIC(19) NOT NULL,
+ stack_id NUMERIC(19) NOT NULL,
+ extension_id NUMERIC(19) NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY (link_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id),
+ CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id));
CREATE TABLE adminresourcetype (
resource_type_id NUMBER(10) NOT NULL,
@@ -167,7 +183,7 @@ CREATE TABLE servicecomponentdesiredstate (
service_name VARCHAR2(255) NOT NULL,
recovery_enabled SMALLINT DEFAULT 0 NOT NULL,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id));
@@ -786,7 +802,7 @@ CREATE TABLE remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name));
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name));
CREATE TABLE remoteambariclusterservice(
id NUMBER(19) NOT NULL,
@@ -1051,6 +1067,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_id_
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_group_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_item_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('stack_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('extension_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('link_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_layout_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('topology_host_info_id_seq', 0);
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 04a4361..b13c121 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -22,7 +22,23 @@ CREATE TABLE stack(
stack_name VARCHAR(255) NOT NULL,
stack_version VARCHAR(255) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version));
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version));
+
+CREATE TABLE extension(
+ extension_id BIGINT NOT NULL,
+ extension_name VARCHAR(255) NOT NULL,
+ extension_version VARCHAR(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY (extension_id),
+ CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version));
+
+CREATE TABLE extensionlink(
+ link_id BIGINT NOT NULL,
+ stack_id BIGINT NOT NULL,
+ extension_id BIGINT NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY (link_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id),
+ CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id));
CREATE TABLE adminresourcetype (
resource_type_id INTEGER NOT NULL,
@@ -176,7 +192,7 @@ CREATE TABLE servicecomponentdesiredstate (
service_name VARCHAR(255) NOT NULL,
recovery_enabled SMALLINT NOT NULL DEFAULT 0,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id));
@@ -788,7 +804,7 @@ CREATE TABLE remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name));
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name));
CREATE TABLE remoteambariclusterservice(
id BIGINT NOT NULL,
@@ -1054,6 +1070,8 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES
('widget_layout_id_seq', 0),
('upgrade_item_id_seq', 0),
('stack_id_seq', 0),
+ ('extension_id_seq', 0),
+ ('link_id_seq', 0),
('topology_host_info_id_seq', 0),
('topology_host_request_id_seq', 0),
('topology_host_task_id_seq', 0),
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 21e6cec..fd14e80 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
@@ -33,10 +33,28 @@ CREATE TABLE ambari.stack(
stack_name VARCHAR(255) NOT NULL,
stack_version VARCHAR(255) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)
);
GRANT ALL PRIVILEGES ON TABLE ambari.stack TO :username;
+CREATE TABLE ambari.extension(
+ extension_id BIGINT NOT NULL,
+ extension_name VARCHAR(255) NOT NULL,
+ extension_version VARCHAR(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY (extension_id),
+ CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version));
+GRANT ALL PRIVILEGES ON TABLE ambari.extension TO :username;
+
+CREATE TABLE ambari.extensionlink(
+ link_id BIGINT NOT NULL,
+ stack_id BIGINT NOT NULL,
+ extension_id BIGINT NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY (link_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES ambari.stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES ambari.extension(extension_id),
+ CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id));
+GRANT ALL PRIVILEGES ON TABLE ambari.extensionlink TO :username;
+
CREATE TABLE ambari.adminresourcetype (
resource_type_id INTEGER NOT NULL,
resource_type_name VARCHAR(255) NOT NULL,
@@ -215,7 +233,7 @@ CREATE TABLE ambari.servicecomponentdesiredstate (
service_name VARCHAR(255) NOT NULL,
recovery_enabled SMALLINT NOT NULL DEFAULT 0,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES ambari.stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES ambari.clusterservices (service_name, cluster_id)
);
@@ -924,7 +942,7 @@ CREATE TABLE ambari.remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)
);
GRANT ALL PRIVILEGES ON TABLE ambari.remoteambaricluster TO :username;
@@ -1216,6 +1234,8 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value) VALUES
('widget_layout_id_seq', 0),
('upgrade_item_id_seq', 0),
('stack_id_seq', 0),
+ ('extension_id_seq', 0),
+ ('link_id_seq', 0),
('topology_host_info_id_seq', 0),
('topology_host_request_id_seq', 0),
('topology_host_task_id_seq', 0),
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 24c1b63..0574c2b 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -21,7 +21,23 @@ CREATE TABLE stack(
stack_name VARCHAR(255) NOT NULL,
stack_version VARCHAR(255) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version));
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version));
+
+CREATE TABLE extension(
+ extension_id NUMERIC(19) NOT NULL,
+ extension_name VARCHAR(255) NOT NULL,
+ extension_version VARCHAR(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY (extension_id),
+ CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version));
+
+CREATE TABLE extensionlink(
+ link_id NUMERIC(19) NOT NULL,
+ stack_id NUMERIC(19) NOT NULL,
+ extension_id NUMERIC(19) NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY (link_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id),
+ CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id));
CREATE TABLE adminresourcetype (
resource_type_id INTEGER NOT NULL,
@@ -165,7 +181,7 @@ CREATE TABLE servicecomponentdesiredstate (
service_name VARCHAR(255) NOT NULL,
recovery_enabled SMALLINT NOT NULL DEFAULT 0,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id));
@@ -785,7 +801,7 @@ CREATE TABLE remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name));
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name));
CREATE TABLE remoteambariclusterservice(
id NUMERIC(19) NOT NULL,
@@ -1050,6 +1066,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_id_
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_group_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_item_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('stack_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('extension_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('link_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_layout_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('topology_host_info_id_seq', 0);
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 cef4866..02becf2 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -34,7 +34,23 @@ CREATE TABLE stack(
stack_name VARCHAR(255) NOT NULL,
stack_version VARCHAR(255) NOT NULL,
CONSTRAINT PK_stack PRIMARY KEY CLUSTERED (stack_id),
- CONSTRAINT unq_stack UNIQUE (stack_name, stack_version));
+ CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version));
+
+CREATE TABLE extension(
+ extension_id BIGINT NOT NULL,
+ extension_name VARCHAR(255) NOT NULL,
+ extension_version VARCHAR(255) NOT NULL,
+ CONSTRAINT PK_extension PRIMARY KEY CLUSTERED (extension_id),
+ CONSTRAINT UQ_extension UNIQUE (extension_name, extension_version));
+
+CREATE TABLE extensionlink(
+ link_id BIGINT NOT NULL,
+ stack_id BIGINT NOT NULL,
+ extension_id BIGINT NOT NULL,
+ CONSTRAINT PK_extensionlink PRIMARY KEY CLUSTERED (link_id),
+ CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+ CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id),
+ CONSTRAINT UQ_extension_link UNIQUE (stack_id, extension_id);
CREATE TABLE adminresourcetype (
resource_type_id INTEGER NOT NULL,
@@ -189,7 +205,7 @@ CREATE TABLE servicecomponentdesiredstate (
service_name VARCHAR(255) NOT NULL,
recovery_enabled SMALLINT NOT NULL DEFAULT 0,
CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id),
- CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
+ CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id),
CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id));
@@ -806,7 +822,7 @@ CREATE TABLE remoteambaricluster(
url VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id),
- CONSTRAINT unq_remote_ambari_cluster UNIQUE (name));
+ CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name));
CREATE TABLE remoteambariclusterservice(
id BIGINT NOT NULL,
@@ -1078,6 +1094,8 @@ BEGIN TRANSACTION
('widget_layout_id_seq', 0),
('upgrade_item_id_seq', 0),
('stack_id_seq', 0),
+ ('extension_id_seq', 0),
+ ('link_id_seq', 0),
('topology_host_info_id_seq', 0),
('topology_host_request_id_seq', 0),
('topology_host_task_id_seq', 0),
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 5671dcf..d44f484 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -33,6 +33,8 @@
<class>org.apache.ambari.server.orm.entities.ConfigGroupEntity</class>
<class>org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity</class>
<class>org.apache.ambari.server.orm.entities.ExecutionCommandEntity</class>
+ <class>org.apache.ambari.server.orm.entities.ExtensionEntity</class>
+ <class>org.apache.ambari.server.orm.entities.ExtensionLinkEntity</class>
<class>org.apache.ambari.server.orm.entities.GroupEntity</class>
<class>org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity</class>
<class>org.apache.ambari.server.orm.entities.HostComponentStateEntity</class>
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/main/resources/extensions/README.txt
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/extensions/README.txt b/ambari-server/src/main/resources/extensions/README.txt
new file mode 100644
index 0000000..865dfc0
--- /dev/null
+++ b/ambari-server/src/main/resources/extensions/README.txt
@@ -0,0 +1,31 @@
+Extensions should include a folder with the extension name.
+Subfolders of the extension name folder represents different
+extension versions.
+
+For a sample extension MY_EXT 1.0, I would create subfolders: MY_EXT/1.0
+
+Within each extension version folder, there should be both a metainfo.xml
+file and a services folder. The metainfo.xml should contain the
+stack versions with which the extension version are compatible.
+
+For example the following metainfo.xml shows an extension that is
+compatible with both HDP 2.4 and HDP 2.5:
+
+<metainfo>
+ <prerequisites>
+ <min-stack-versions>
+ <stack>
+ <name>HDP</name>
+ <version>2.4</version>
+ </stack>
+ <stack>
+ <name>HDP</name>
+ <version>2.5</version>
+ </stack>
+ </min-stack-versions>
+ </prerequisites>
+</metainfo>
+
+The services folder will contain all services that are part of the
+extension version. The contents of those service folders will be the
+same as what you would find in under a stack version's services folder.
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/main/resources/key_properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/key_properties.json b/ambari-server/src/main/resources/key_properties.json
index 8069349..df2006a 100644
--- a/ambari-server/src/main/resources/key_properties.json
+++ b/ambari-server/src/main/resources/key_properties.json
@@ -79,13 +79,27 @@
"StackService": "StackServiceComponents/service_name",
"StackServiceComponent": "StackServiceComponents/component_name"
},
- "StackServiceComponentDependency": {
+ "StackServiceComponentDependency": {
"Stack": "Dependencies/stack_name",
"StackVersion": "Dependencies/stack_version",
"StackService": "Dependencies/dependent_service_name",
"StackServiceComponent": "Dependencies/dependent_component_name",
"StackServiceComponentDependency": "Dependencies/component_name"
},
+ "ExtensionLink": {
+ "ExtensionLink": "ExtensionLink/link_id",
+ "Stack": "ExtensionLink/stack_name",
+ "StackVersion": "ExtensionLink/stack_version",
+ "Extension": "ExtensionLink/extension_name",
+ "ExtensionVersion": "ExtensionLink/extension_version"
+ },
+ "Extension": {
+ "Extension": "Extensions/extension_name"
+ },
+ "ExtensionVersion": {
+ "Extension": "Versions/extension_name",
+ "ExtensionVersion": "Versions/extension_version"
+ },
"DRFeed": {
"DRFeed": "Feed/name"
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/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 eac0dbd..f471628 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -265,6 +265,26 @@
"auto_deploy/enabled",
"auto_deploy/location"
],
+ "ExtensionLink": [
+ "ExtensionLink/link_id",
+ "ExtensionLink/stack_name",
+ "ExtensionLink/stack_version",
+ "ExtensionLink/extension_name",
+ "ExtensionLink/extension_version",
+ "_"
+ ],
+ "Extension":[
+ "Extensions/extension_name",
+ "_"
+ ],
+ "ExtensionVersion":[
+ "Versions/extension_name",
+ "Versions/extension_version",
+ "Versions/valid",
+ "Versions/extension-errors",
+ "Versions/parent_extension_version",
+ "_"
+ ],
"DRFeed":[
"Feed/name",
"Feed/description",
@@ -469,10 +489,10 @@
"StackConfigurationDependency/dependency_name",
"_"
],
- "KerberosDescriptor":[
- "KerberosDescriptors/kerberos_descriptor_name",
- "KerberosDescriptors/kerberos_descriptor_text",
- "_"
- ]
+ "KerberosDescriptor":[
+ "KerberosDescriptors/kerberos_descriptor_name",
+ "KerberosDescriptors/kerberos_descriptor_text",
+ "_"
+ ]
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java
new file mode 100644
index 0000000..97fd2b5
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.notNull;
+import static org.easymock.EasyMock.same;
+import static org.junit.Assert.assertEquals;
+
+/**
+* Unit tests for ExtensionsService.
+*/
+public class ExtensionsServiceTest extends BaseServiceTest {
+
+ @Override
+ public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+ List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+ // getExtension
+ ExtensionsService service = new TestExtensionsService("extensionName", null);
+ Method m = service.getClass().getMethod("getExtension", String.class, HttpHeaders.class, UriInfo.class, String.class);
+ Object[] args = new Object[] {null, getHttpHeaders(), getUriInfo(), "extensionName"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+
+ //getExtensions
+ service = new TestExtensionsService(null, null);
+ m = service.getClass().getMethod("getExtensions", String.class, HttpHeaders.class, UriInfo.class);
+ args = new Object[] {null, getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+
+ // getExtensionVersion
+ service = new TestExtensionsService("extensionName", "extensionVersion");
+ m = service.getClass().getMethod("getExtensionVersion", String.class, HttpHeaders.class, UriInfo.class, String.class, String.class);
+ args = new Object[] {null, getHttpHeaders(), getUriInfo(), "extensionName", "extensionVersion"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+
+ // getExtensionVersions
+ service = new TestExtensionsService("extensionName", null);
+ m = service.getClass().getMethod("getExtensionVersions", String.class, HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {null, getHttpHeaders(), getUriInfo(), "extensionName"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+
+ return listInvocations;
+ }
+
+ private class TestExtensionsService extends ExtensionsService {
+
+ private String m_extensionId;
+ private String m_extensionVersion;
+
+ private TestExtensionsService(String extensionName, String extensionVersion) {
+ m_extensionId = extensionName;
+ m_extensionVersion = extensionVersion;
+ }
+
+ @Override
+ ResourceInstance createExtensionResource(String extensionName) {
+ assertEquals(m_extensionId, extensionName);
+ return getTestResource();
+ }
+
+ @Override
+ ResourceInstance createExtensionVersionResource(String extensionName, String extensionVersion) {
+ assertEquals(m_extensionId, extensionName);
+ assertEquals(m_extensionVersion, extensionVersion);
+ return getTestResource();
+ }
+
+ @Override
+ RequestFactory getRequestFactory() {
+ return getTestRequestFactory();
+ }
+
+ @Override
+ protected RequestBodyParser getBodyParser() {
+ return getTestBodyParser();
+ }
+
+ @Override
+ protected ResultSerializer getResultSerializer() {
+ return getTestResultSerializer();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java
new file mode 100644
index 0000000..8959e4d
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller.internal;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ExtensionRequest;
+import org.apache.ambari.server.controller.ExtensionResponse;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * ExtensionResourceProvider Test
+ */
+public class ExtensionResourceProviderTest {
+ @Test
+ public void testGetResources() throws Exception {
+ Resource.Type type = Resource.Type.Extension;
+
+ AmbariManagementController managementController = createMock(AmbariManagementController.class);
+
+ Set<ExtensionResponse> allResponse = new HashSet<ExtensionResponse>();
+ allResponse.add(new ExtensionResponse("Extension1"));
+ allResponse.add(new ExtensionResponse("Extension2"));
+
+ // set expectations
+ expect(managementController.getExtensions(EasyMock.<Set<ExtensionRequest>>anyObject())).andReturn(allResponse).once();
+
+ // replay
+ replay(managementController);
+
+ ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+ type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ Set<String> propertyIds = new HashSet<String>();
+
+ propertyIds.add(ExtensionResourceProvider.EXTENSION_NAME_PROPERTY_ID);
+
+ // create the request
+ Request request = PropertyHelper.getReadRequest(propertyIds);
+
+ // get all ... no predicate
+ Set<Resource> resources = provider.getResources(request, null);
+
+ Assert.assertEquals(2, resources.size());
+
+
+ Set<String> extensionNames = new HashSet<String>();
+ extensionNames.add("Extension1");
+ extensionNames.add("Extension2");
+
+ for (Resource resource : resources) {
+ String extensionName = (String) resource.getPropertyValue(ExtensionResourceProvider.EXTENSION_NAME_PROPERTY_ID);
+ Assert.assertTrue(extensionNames.contains(extensionName));
+ }
+
+ // verify
+ verify(managementController);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
index a02311a..f21b250 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java
@@ -495,7 +495,7 @@ public class ComponentModuleTest {
ComponentModule component = new ComponentModule(info);
ComponentModule parentComponent = new ComponentModule(parentInfo);
- component.resolve(parentComponent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap());
+ component.resolve(parentComponent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap(), Collections.<String, ExtensionModule>emptyMap());
return component;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
index 8fcc76e..38176aa 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java
@@ -118,11 +118,11 @@ public class QuickLinksConfigurationModuleTest {
QuickLinksConfigurationModule parentModule = new QuickLinksConfigurationModule(parentQuiclinksFile);
QuickLinksConfigurationModule childModule = new QuickLinksConfigurationModule(childQuickLinksFile);
- childModule.resolve(parentModule, null, null);
+ childModule.resolve(parentModule, null, null, null);
QuickLinks parentQuickLinks = parentModule.getModuleInfo().getQuickLinksConfigurationMap().get(QuickLinksConfigurationModule.QUICKLINKS_CONFIGURATION_KEY);
QuickLinks childQuickLinks = childModule.getModuleInfo().getQuickLinksConfigurationMap().get(QuickLinksConfigurationModule.QUICKLINKS_CONFIGURATION_KEY);
return new QuickLinks[]{parentQuickLinks, childQuickLinks};
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
index c9bcf60..304fd5c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
@@ -1211,7 +1211,7 @@ public class ServiceModuleTest {
}
private void resolveService(ServiceModule service, ServiceModule parent) throws AmbariException {
- service.resolve(parent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap());
+ service.resolve(parent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap(), Collections.<String, ExtensionModule>emptyMap());
// during runtime this would be called by the Stack module when it's resolve completed
service.finalizeModule();
parent.finalizeModule();
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
index 969e07c..1d73ff3 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java
@@ -29,14 +29,19 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.CommandScriptDefinition;
import org.apache.ambari.server.state.ComponentInfo;
@@ -58,6 +63,8 @@ public class StackManagerCommonServicesTest {
private static StackManager stackManager;
private static MetainfoDAO metaInfoDao;
private static StackDAO stackDao;
+ private static ExtensionDAO extensionDao;
+ private static ExtensionLinkDAO linkDao;
private static ActionMetadata actionMetadata;
private static OsFamily osFamily;
@@ -72,17 +79,22 @@ public class StackManagerCommonServicesTest {
String commonServices = ClassLoader.getSystemClassLoader().getResource(
"common-services").getPath();
- return createTestStackManager(stack, commonServices);
+ String extensions = ClassLoader.getSystemClassLoader().getResource(
+ "extensions").getPath();
+ return createTestStackManager(stack, commonServices, extensions);
}
public static StackManager createTestStackManager(String stackRoot,
- String commonServicesRoot) throws Exception {
+ String commonServicesRoot, String extensionRoot) throws Exception {
// todo: dao , actionMetaData expectations
metaInfoDao = createNiceMock(MetainfoDAO.class);
stackDao = createNiceMock(StackDAO.class);
+ extensionDao = createNiceMock(ExtensionDAO.class);
+ linkDao = createNiceMock(ExtensionLinkDAO.class);
actionMetadata = createNiceMock(ActionMetadata.class);
Configuration config = createNiceMock(Configuration.class);
StackEntity stackEntity = createNiceMock(StackEntity.class);
+ ExtensionEntity extensionEntity = createNiceMock(ExtensionEntity.class);
expect(config.getSharedResourcesDirPath()).andReturn(
ClassLoader.getSystemClassLoader().getResource("").getPath()).anyTimes();
@@ -91,13 +103,25 @@ public class StackManagerCommonServicesTest {
stackDao.find(EasyMock.anyObject(String.class),
EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce();
- replay(config, stackDao);
+
+ expect(
+ extensionDao.find(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(extensionEntity).atLeastOnce();
+
+ List<ExtensionLinkEntity> list = Collections.emptyList();
+ expect(
+ linkDao.findByStack(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce();
+
+ replay(config, stackDao, extensionDao, linkDao);
+
osFamily = new OsFamily(config);
replay(metaInfoDao, actionMetadata);
StackManager stackManager = new StackManager(new File(stackRoot), new File(
- commonServicesRoot), osFamily, false, metaInfoDao, actionMetadata, stackDao);
+ commonServicesRoot), new File(extensionRoot), osFamily, true, metaInfoDao,
+ actionMetadata, stackDao, extensionDao, linkDao);
EasyMock.verify( config, stackDao );
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java
new file mode 100644
index 0000000..659ae12
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.stack;
+
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+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;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ * StackManager extension unit tests.
+ */
+public class StackManagerExtensionTest {
+
+ @Test
+ public void testExtensions() throws Exception {
+ MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class);
+ StackDAO stackDao = createNiceMock(StackDAO.class);
+ ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class);
+ ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class);
+ ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
+ OsFamily osFamily = createNiceMock(OsFamily.class);
+ StackEntity stackEntity = createNiceMock(StackEntity.class);
+ ExtensionEntity extensionEntity = createNiceMock(ExtensionEntity.class);
+ ExtensionLinkEntity linkEntity = createNiceMock(ExtensionLinkEntity.class);
+ List<ExtensionLinkEntity> list = new ArrayList<ExtensionLinkEntity>();
+ list.add(linkEntity);
+
+ expect(
+ stackDao.find(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce();
+
+ expect(
+ extensionDao.find(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(extensionEntity).atLeastOnce();
+
+ expect(
+ linkDao.findByStack(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce();
+
+ expect(
+ linkEntity.getExtension()).andReturn(extensionEntity).atLeastOnce();
+
+ expect(
+ extensionEntity.getExtensionName()).andReturn("EXT").atLeastOnce();
+
+ expect(
+ extensionEntity.getExtensionVersion()).andReturn("0.2").atLeastOnce();
+
+ replay(actionMetadata, stackDao, metaInfoDao, osFamily, extensionDao, linkDao, extensionEntity, linkEntity);
+
+ String stacks = ClassLoader.getSystemClassLoader().getResource("stacks_with_extensions").getPath();
+ String common = ClassLoader.getSystemClassLoader().getResource("common-services").getPath();
+ String extensions = ClassLoader.getSystemClassLoader().getResource("extensions").getPath();
+
+ StackManager stackManager = new StackManager(new File(stacks),
+ new File(common), new File(extensions), osFamily, false,
+ metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao);
+
+ ExtensionInfo extension = stackManager.getExtension("EXT", "0.1");
+ assertNull("EXT 0.1's parent: " + extension.getParentExtensionVersion(), extension.getParentExtensionVersion());
+ assertNotNull(extension.getService("OOZIE2"));
+ ServiceInfo oozie = extension.getService("OOZIE2");
+ assertNotNull("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder());
+ assertTrue("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder().contains("extensions/EXT/0.1/services/OOZIE2/package"));
+ assertEquals(oozie.getVersion(), "3.2.0");
+
+ extension = stackManager.getExtension("EXT", "0.2");
+ assertNotNull("EXT 0.2's parent: " + extension.getParentExtensionVersion(), extension.getParentExtensionVersion());
+ assertEquals("EXT 0.2's parent: " + extension.getParentExtensionVersion(), "0.1", extension.getParentExtensionVersion());
+ assertNotNull(extension.getService("OOZIE2"));
+ oozie = extension.getService("OOZIE2");
+ assertNotNull("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder());
+ assertTrue("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder().contains("extensions/EXT/0.1/services/OOZIE2/package"));
+ assertEquals(oozie.getVersion(), "4.0.0");
+
+ StackInfo stack = stackManager.getStack("HDP", "0.2");
+ assertNotNull(stack.getService("OOZIE2"));
+ oozie = stack.getService("OOZIE2");
+ assertNotNull("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder());
+ assertTrue("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder().contains("extensions/EXT/0.1/services/OOZIE2/package"));
+ assertEquals(oozie.getVersion(), "4.0.0");
+
+ assertTrue("Extensions found: " + stack.getExtensions().size(), stack.getExtensions().size() == 1);
+ extension = stack.getExtensions().iterator().next();
+ assertEquals("Extension name: " + extension.getName(), extension.getName(), "EXT");
+ assertEquals("Extension version: " + extension.getVersion(), extension.getVersion(), "0.2");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/300a7e21/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
index 55a3c46..ca24cd9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java
@@ -28,11 +28,16 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import org.apache.ambari.server.AmbariException;
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.ExtensionLinkEntity;
import org.apache.ambari.server.orm.entities.StackEntity;
import org.apache.ambari.server.state.StackInfo;
import org.apache.ambari.server.state.stack.OsFamily;
@@ -48,6 +53,8 @@ public class StackManagerMiscTest {
public void testCycleDetection() throws Exception {
MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class);
StackDAO stackDao = createNiceMock(StackDAO.class);
+ ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class);
+ ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class);
ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
OsFamily osFamily = createNiceMock(OsFamily.class);
StackEntity stackEntity = createNiceMock(StackEntity.class);
@@ -56,13 +63,18 @@ public class StackManagerMiscTest {
stackDao.find(EasyMock.anyObject(String.class),
EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce();
- replay(actionMetadata, stackDao, metaInfoDao, osFamily);
+ List<ExtensionLinkEntity> list = Collections.emptyList();
+ expect(
+ linkDao.findByStack(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce();
+
+ replay(actionMetadata, stackDao, extensionDao, linkDao, metaInfoDao, osFamily);
try {
String stacksCycle1 = ClassLoader.getSystemClassLoader().getResource("stacks_with_cycle").getPath();
- StackManager stackManager = new StackManager(new File(stacksCycle1),
- null, osFamily, false, metaInfoDao, actionMetadata, stackDao);
+ StackManager stackManager = new StackManager(new File(stacksCycle1), null, null, osFamily, false,
+ metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao);
fail("Expected exception due to cyclic stack");
} catch (AmbariException e) {
@@ -74,7 +86,7 @@ public class StackManagerMiscTest {
"stacks_with_cycle2").getPath();
StackManager stackManager = new StackManager(new File(stacksCycle2),
- null, osFamily, true, metaInfoDao, actionMetadata, stackDao);
+ null, null, osFamily, true, metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao);
fail("Expected exception due to cyclic stack");
} catch (AmbariException e) {
@@ -91,6 +103,8 @@ public class StackManagerMiscTest {
public void testGetServiceInfoFromSingleStack() throws Exception {
MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class);
StackDAO stackDao = createNiceMock(StackDAO.class);
+ ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class);
+ ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class);
ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
OsFamily osFamily = createNiceMock(OsFamily.class);
StackEntity stackEntity = createNiceMock(StackEntity.class);
@@ -102,14 +116,18 @@ public class StackManagerMiscTest {
stackDao.find(EasyMock.anyObject(String.class),
EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce();
- replay(metaInfoDao, stackDao, actionMetadata, osFamily);
+ List<ExtensionLinkEntity> list = Collections.emptyList();
+ expect(
+ linkDao.findByStack(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce();
+
+ replay(metaInfoDao, stackDao, extensionDao, linkDao, actionMetadata, osFamily);
String singleStack = ClassLoader.getSystemClassLoader().getResource("single_stack").getPath();
StackManager stackManager = new StackManager(new File(singleStack.replace(
- StackManager.PATH_DELIMITER, File.separator)),
- null, osFamily, false, metaInfoDao, actionMetadata, stackDao);
-
+ StackManager.PATH_DELIMITER, File.separator)), null, null, osFamily, false, metaInfoDao,
+ actionMetadata, stackDao, extensionDao, linkDao);
Collection<StackInfo> stacks = stackManager.getStacks();
assertEquals(1, stacks.size());
@@ -126,6 +144,8 @@ public class StackManagerMiscTest {
public void testCircularDependencyForServiceUpgrade() throws Exception {
MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class);
StackDAO stackDao = createNiceMock(StackDAO.class);
+ ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class);
+ ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class);
ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class);
OsFamily osFamily = createNiceMock(OsFamily.class);
StackEntity stackEntity = createNiceMock(StackEntity.class);
@@ -134,13 +154,18 @@ public class StackManagerMiscTest {
stackDao.find(EasyMock.anyObject(String.class),
EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce();
- replay(actionMetadata, stackDao, metaInfoDao, osFamily);
+ List<ExtensionLinkEntity> list = Collections.emptyList();
+ expect(
+ linkDao.findByStack(EasyMock.anyObject(String.class),
+ EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce();
+
+ replay(metaInfoDao, stackDao, extensionDao, linkDao, actionMetadata, osFamily);
try {
String upgradeCycle = ClassLoader.getSystemClassLoader().getResource("stacks_with_upgrade_cycle").getPath();
- StackManager stackManager = new StackManager(new File(upgradeCycle),
- null, osFamily, false, metaInfoDao, actionMetadata, stackDao);
+ StackManager stackManager = new StackManager(new File(upgradeCycle), null, null, osFamily, false,
+ metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao);
fail("Expected exception due to cyclic service upgrade xml");
} catch (AmbariException e) {