You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mr...@apache.org on 2017/11/27 23:29:22 UTC
[10/30] ambari git commit: Merge trunk with feature branch and fix
some UT compilation issues (mradhakrishnan)
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
index 0997f65..bbcd6e8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
@@ -18,21 +18,17 @@
package org.apache.ambari.server.serveraction.kerberos;
-import java.text.NumberFormat;
-import java.text.ParseException;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Queue;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.Set;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.utils.ShellCommandUtil;
-import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,37 +41,24 @@ import com.google.inject.Inject;
* It is assumed that a MIT Kerberos client is installed and that the kdamin shell command is
* available
*/
-public class MITKerberosOperationHandler extends KerberosOperationHandler {
+public class MITKerberosOperationHandler extends KDCKerberosOperationHandler {
+
+ private final static Logger LOG = LoggerFactory.getLogger(MITKerberosOperationHandler.class);
@Inject
private Configuration configuration;
/**
- * A regular expression pattern to use to parse the key number from the text captured from the
- * get_principal kadmin command
- */
- private final static Pattern PATTERN_GET_KEY_NUMBER = Pattern.compile("^.*?Key: vno (\\d+).*$", Pattern.DOTALL);
-
- private final static Logger LOG = LoggerFactory.getLogger(MITKerberosOperationHandler.class);
-
- /**
* A String containing user-specified attributes used when creating principals
*/
private String createAttributes = null;
- private String adminServerHost = null;
-
/**
* A String containing the resolved path to the kdamin executable
*/
private String executableKadmin = null;
/**
- * A String containing the resolved path to the kdamin.local executable
- */
- private String executableKadminLocal = null;
-
- /**
* Prepares and creates resources to be used by this KerberosOperationHandler
* <p/>
* It is expected that this KerberosOperationHandler will not be used before this call.
@@ -92,39 +75,25 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* @throws KerberosOperationException if an unexpected error occurred
*/
@Override
- public void open(PrincipalKeyCredential administratorCredentials, String realm,
- Map<String, String> kerberosConfiguration)
+ public void open(PrincipalKeyCredential administratorCredentials, String realm, Map<String, String> kerberosConfiguration)
throws KerberosOperationException {
- setAdministratorCredential(administratorCredentials);
- setDefaultRealm(realm);
-
if (kerberosConfiguration != null) {
- setKeyEncryptionTypes(translateEncryptionTypes(kerberosConfiguration.get(KERBEROS_ENV_ENCRYPTION_TYPES), "\\s+"));
- setAdminServerHost(kerberosConfiguration.get(KERBEROS_ENV_ADMIN_SERVER_HOST));
- setExecutableSearchPaths(kerberosConfiguration.get(KERBEROS_ENV_EXECUTABLE_SEARCH_PATHS));
- setCreateAttributes(kerberosConfiguration.get(KERBEROS_ENV_KDC_CREATE_ATTRIBUTES));
- } else {
- setKeyEncryptionTypes(null);
- setAdminServerHost(null);
- setExecutableSearchPaths((String) null);
- setCreateAttributes(null);
+ createAttributes = kerberosConfiguration.get(KERBEROS_ENV_KDC_CREATE_ATTRIBUTES);
}
// Pre-determine the paths to relevant Kerberos executables
executableKadmin = getExecutable("kadmin");
- executableKadminLocal = getExecutable("kadmin.local");
- setOpen(true);
+ super.open(administratorCredentials, realm, kerberosConfiguration);
}
@Override
public void close() throws KerberosOperationException {
- // There is nothing to do here.
- setOpen(false);
-
+ createAttributes = null;
executableKadmin = null;
- executableKadminLocal = null;
+
+ super.close();
}
/**
@@ -134,6 +103,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* the result from STDOUT to determine if the presence of the specified principal.
*
* @param principal a String containing the principal to test
+ * @param service a boolean value indicating whether the principal is for a service or not
* @return true if the principal exists; false otherwise
* @throws KerberosKDCConnectionException if a connection to the KDC cannot be made
* @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
@@ -141,26 +111,25 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* @throws KerberosOperationException if an unexpected error occurred
*/
@Override
- public boolean principalExists(String principal)
+ public boolean principalExists(String principal, boolean service)
throws KerberosOperationException {
if (!isOpen()) {
throw new KerberosOperationException("This operation handler has not been opened");
}
- if (principal == null) {
- return false;
- } else {
+ if (!StringUtils.isEmpty(principal)) {
// Create the KAdmin query to execute:
- ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal), null);
+ ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal));
// If there is data from STDOUT, see if the following string exists:
// Principal: <principal>
String stdOut = result.getStdout();
return (stdOut != null) && stdOut.contains(String.format("Principal: %s", principal));
}
- }
+ return false;
+ }
/**
* Creates a new principal in a previously configured MIT KDC
@@ -188,72 +157,25 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
if (StringUtils.isEmpty(principal)) {
throw new KerberosOperationException("Failed to create new principal - no principal specified");
- } else if (StringUtils.isEmpty(password)) {
- throw new KerberosOperationException("Failed to create new principal - no password specified");
- } else {
- String createAttributes = getCreateAttributes();
- // Create the kdamin query: add_principal <-randkey|-pw <password>> [<options>] <principal>
- ShellCommandUtil.Result result = invokeKAdmin(String.format("add_principal %s %s",
- (createAttributes == null) ? "" : createAttributes, principal), password);
-
- // If there is data from STDOUT, see if the following string exists:
- // Principal "<principal>" created
- String stdOut = result.getStdout();
- String stdErr = result.getStderr();
- if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) {
- return getKeyNumber(principal);
- } else if ((stdErr != null) && stdErr.contains(String.format("Principal or policy already exists while creating \"%s\"", principal))) {
- throw new KerberosPrincipalAlreadyExistsException(principal);
- } else {
- LOG.error("Failed to execute kadmin query: add_principal -pw \"********\" {} {}\nSTDOUT: {}\nSTDERR: {}",
- (createAttributes == null) ? "" : createAttributes, principal, stdOut, result.getStderr());
- throw new KerberosOperationException(String.format("Failed to create service principal for %s\nSTDOUT: %s\nSTDERR: %s",
- principal, stdOut, result.getStderr()));
- }
- }
- }
-
- /**
- * Updates the password for an existing principal in a previously configured MIT KDC
- * <p/>
- * This implementation creates a query to send to the kadmin shell command and then interrogates
- * the exit code to determine if the operation executed successfully.
- *
- * @param principal a String containing the principal to update
- * @param password a String containing the password to set
- * @return an Integer declaring the new key number
- * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made
- * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
- * @throws KerberosRealmException if the realm does not map to a KDC
- * @throws KerberosPrincipalDoesNotExistException if the principal does not exist
- * @throws KerberosOperationException if an unexpected error occurred
- */
- @Override
- public Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException {
- if (!isOpen()) {
- throw new KerberosOperationException("This operation handler has not been opened");
}
- if (StringUtils.isEmpty(principal)) {
- throw new KerberosOperationException("Failed to set password - no principal specified");
- } else if (StringUtils.isEmpty(password)) {
- throw new KerberosOperationException("Failed to set password - no password specified");
+ // Create the kdamin query: add_principal <-randkey|-pw <password>> [<options>] <principal>
+ ShellCommandUtil.Result result = invokeKAdmin(String.format("add_principal -randkey %s %s",
+ (createAttributes == null) ? "" : createAttributes, principal));
+
+ // If there is data from STDOUT, see if the following string exists:
+ // Principal "<principal>" created
+ String stdOut = result.getStdout();
+ String stdErr = result.getStderr();
+ if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) {
+ return 0;
+ } else if ((stdErr != null) && stdErr.contains(String.format("Principal or policy already exists while creating \"%s\"", principal))) {
+ throw new KerberosPrincipalAlreadyExistsException(principal);
} else {
- // Create the kdamin query: change_password <-randkey|-pw <password>> <principal>
- ShellCommandUtil.Result result = invokeKAdmin(String.format("change_password %s", principal), password);
-
- String stdOut = result.getStdout();
- String stdErr = result.getStderr();
- if ((stdOut != null) && stdOut.contains(String.format("Password for \"%s\" changed", principal))) {
- return getKeyNumber(principal);
- } else if ((stdErr != null) && stdErr.contains("Principal does not exist")) {
- throw new KerberosPrincipalDoesNotExistException(principal);
- } else {
- LOG.error("Failed to execute kadmin query: change_password -pw \"********\" {} \nSTDOUT: {}\nSTDERR: {}",
- principal, stdOut, result.getStderr());
- throw new KerberosOperationException(String.format("Failed to update password for %s\nSTDOUT: %s\nSTDERR: %s",
- principal, stdOut, result.getStderr()));
- }
+ LOG.error("Failed to execute kadmin query: add_principal -pw \"********\" {} {}\nSTDOUT: {}\nSTDERR: {}",
+ (createAttributes == null) ? "" : createAttributes, principal, stdOut, result.getStderr());
+ throw new KerberosOperationException(String.format("Failed to create service principal for %s\nSTDOUT: %s\nSTDERR: %s",
+ principal, stdOut, result.getStderr()));
}
}
@@ -263,6 +185,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* The implementation is specific to a particular type of KDC.
*
* @param principal a String containing the principal to remove
+ * @param service a boolean value indicating whether the principal is for a service or not
* @return true if the principal was successfully removed; otherwise false
* @throws KerberosKDCConnectionException if a connection to the KDC cannot be made
* @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
@@ -270,181 +193,63 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* @throws KerberosOperationException if an unexpected error occurred
*/
@Override
- public boolean removePrincipal(String principal) throws KerberosOperationException {
+ public boolean removePrincipal(String principal, boolean service) throws KerberosOperationException {
if (!isOpen()) {
throw new KerberosOperationException("This operation handler has not been opened");
}
if (StringUtils.isEmpty(principal)) {
- throw new KerberosOperationException("Failed to remove new principal - no principal specified");
- } else {
- ShellCommandUtil.Result result = invokeKAdmin(String.format("delete_principal -force %s", principal), null);
-
- // If there is data from STDOUT, see if the following string exists:
- // Principal "<principal>" created
- String stdOut = result.getStdout();
- return (stdOut != null) && !stdOut.contains("Principal does not exist");
+ throw new KerberosOperationException("Failed to remove principal - no principal specified");
}
- }
- /**
- * Sets the KDC administrator server host address
- *
- * @param adminServerHost the ip address or FQDN of the KDC administrator server
- */
- public void setAdminServerHost(String adminServerHost) {
- this.adminServerHost = adminServerHost;
- }
+ ShellCommandUtil.Result result = invokeKAdmin(String.format("delete_principal -force %s", principal));
- /**
- * Gets the IP address or FQDN of the KDC administrator server
- *
- * @return the IP address or FQDN of the KDC administrator server
- */
- public String getAdminServerHost() {
- return this.adminServerHost;
- }
-
- /**
- * Sets the (additional) principal creation attributes
- *
- * @param createAttributes the additional principal creations attributes
- */
- public void setCreateAttributes(String createAttributes) {
- this.createAttributes = createAttributes;
- }
-
- /**
- * Gets the (additional) principal creation attributes
- *
- * @return the additional principal creations attributes or null
- */
- public String getCreateAttributes() {
- return createAttributes;
- }
-
- /**
- * Retrieves the current key number assigned to the identity identified by the specified principal
- *
- * @param principal a String declaring the principal to look up
- * @return an Integer declaring the current key number
- * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made
- * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
- * @throws KerberosRealmException if the realm does not map to a KDC
- * @throws KerberosOperationException if an unexpected error occurred
- */
- private Integer getKeyNumber(String principal) throws KerberosOperationException {
- if (!isOpen()) {
- throw new KerberosOperationException("This operation handler has not been opened");
- }
-
- if (StringUtils.isEmpty(principal)) {
- throw new KerberosOperationException("Failed to get key number for principal - no principal specified");
- } else {
- // Create the kdamin query: get_principal <principal>
- ShellCommandUtil.Result result = invokeKAdmin(String.format("get_principal %s", principal), null);
-
- String stdOut = result.getStdout();
- if (stdOut == null) {
- String message = String.format("Failed to get key number for %s:\n\tExitCode: %s\n\tSTDOUT: NULL\n\tSTDERR: %s",
- principal, result.getExitCode(), result.getStderr());
- LOG.warn(message);
- throw new KerberosOperationException(message);
- }
-
- Matcher matcher = PATTERN_GET_KEY_NUMBER.matcher(stdOut);
- if (matcher.matches()) {
- NumberFormat numberFormat = NumberFormat.getIntegerInstance();
- String keyNumber = matcher.group(1);
-
- numberFormat.setGroupingUsed(false);
- try {
- Number number = numberFormat.parse(keyNumber);
- return (number == null) ? 0 : number.intValue();
- } catch (ParseException e) {
- String message = String.format("Failed to get key number for %s - invalid key number value (%s):\n\tExitCode: %s\n\tSTDOUT: NULL\n\tSTDERR: %s",
- principal, keyNumber, result.getExitCode(), result.getStderr());
- LOG.warn(message);
- throw new KerberosOperationException(message);
- }
- } else {
- String message = String.format("Failed to get key number for %s - unexpected STDOUT data:\n\tExitCode: %s\n\tSTDOUT: NULL\n\tSTDERR: %s",
- principal, result.getExitCode(), result.getStderr());
- LOG.warn(message);
- throw new KerberosOperationException(message);
- }
- }
+ // If there is data from STDOUT, see if the following string exists:
+ // Principal "<principal>" created
+ String stdOut = result.getStdout();
+ return (stdOut != null) && !stdOut.contains("Principal does not exist");
}
/**
* Invokes the kadmin shell command to issue queries
*
- * @param query a String containing the query to send to the kdamin command
- * @param userPassword a String containing the user's password to set or update if necessary,
- * null if not needed
+ * @param query a String containing the query to send to the kdamin command
* @return a ShellCommandUtil.Result containing the result of the operation
* @throws KerberosKDCConnectionException if a connection to the KDC cannot be made
* @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
* @throws KerberosRealmException if the realm does not map to a KDC
* @throws KerberosOperationException if an unexpected error occurred
*/
- protected ShellCommandUtil.Result invokeKAdmin(String query, String userPassword)
+ protected ShellCommandUtil.Result invokeKAdmin(String query)
throws KerberosOperationException {
if (StringUtils.isEmpty(query)) {
throw new KerberosOperationException("Missing kadmin query");
}
- ShellCommandUtil.Result result = null;
- PrincipalKeyCredential administratorCredential = getAdministratorCredential();
- String defaultRealm = getDefaultRealm();
+ if (StringUtils.isEmpty(executableKadmin)) {
+ throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened.");
+ }
List<String> command = new ArrayList<>();
+ command.add(executableKadmin);
- String adminPrincipal = (administratorCredential == null)
- ? null
- : administratorCredential.getPrincipal();
-
- ShellCommandUtil.InteractiveHandler interactiveHandler = null;
-
- if (StringUtils.isEmpty(adminPrincipal)) {
- // Set the kdamin interface to be kadmin.local
- if (StringUtils.isEmpty(executableKadminLocal)) {
- throw new KerberosOperationException("No path for kadmin.local is available - this KerberosOperationHandler may not have been opened.");
- }
-
- command.add(executableKadminLocal);
-
- if (userPassword != null) {
- interactiveHandler = new InteractivePasswordHandler(null, userPassword);
- }
- } else {
- if (StringUtils.isEmpty(executableKadmin)) {
- throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened.");
- }
- char[] adminPassword = administratorCredential.getKey();
-
- // Set the kdamin interface to be kadmin
- command.add(executableKadmin);
-
- // Add explicit KDC admin host, if available
- if (!StringUtils.isEmpty(getAdminServerHost())) {
- command.add("-s");
- command.add(getAdminServerHost());
- }
-
- // Add the administrative principal
- command.add("-p");
- command.add(adminPrincipal);
+ // Add the credential cache, if available
+ String credentialCacheFilePath = getCredentialCacheFilePath();
+ if (!StringUtils.isEmpty(credentialCacheFilePath)) {
+ command.add("-c");
+ command.add(credentialCacheFilePath);
+ }
- if (!ArrayUtils.isEmpty(adminPassword)) {
- interactiveHandler = new InteractivePasswordHandler(String.valueOf(adminPassword), userPassword);
- } else if (userPassword != null) {
- interactiveHandler = new InteractivePasswordHandler(null, userPassword);
- }
+ // Add explicit KDC admin host, if available
+ String adminSeverHost = getAdminServerHost();
+ if (!StringUtils.isEmpty(adminSeverHost)) {
+ command.add("-s");
+ command.add(adminSeverHost);
}
+ // Add default realm clause, if available
+ String defaultRealm = getDefaultRealm();
if (!StringUtils.isEmpty(defaultRealm)) {
- // Add default realm clause
command.add("-r");
command.add(defaultRealm);
}
@@ -457,12 +262,13 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
LOG.debug("Executing: {}", command);
}
+ ShellCommandUtil.Result result = null;
int retryCount = configuration.getKerberosOperationRetries();
int tries = 0;
while (tries <= retryCount) {
try {
- result = executeCommand(command.toArray(new String[command.size()]), null, interactiveHandler);
+ result = executeCommand(command.toArray(new String[command.size()]));
} catch (KerberosOperationException exception) {
if (tries == retryCount) {
throw exception;
@@ -486,13 +292,16 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
}
- if (!result.isSuccessful()) {
+ if ((result == null) || !result.isSuccessful()) {
+ int exitCode = (result == null) ? -999 : result.getExitCode();
+ String stdOut = (result == null) ? "" : result.getStdout();
+ String stdErr = (result == null) ? "" : result.getStderr();
+
String message = String.format("Failed to execute kadmin:\n\tCommand: %s\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",
- command, result.getExitCode(), result.getStdout(), result.getStderr());
+ command, exitCode, stdOut, stdErr);
LOG.warn(message);
// Test STDERR to see of any "expected" error conditions were encountered...
- String stdErr = result.getStderr();
// Did admin credentials fail?
if (stdErr.contains("Client not found in Kerberos database")) {
throw new KerberosAdminAuthenticationException(stdErr);
@@ -513,57 +322,56 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
} else {
throw new KerberosOperationException(String.format("Unexpected error condition executing the kadmin command. STDERR: %s", stdErr));
}
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Executed the following command:\n{}\nSTDOUT: {}\nSTDERR: {}",
+ StringUtils.join(command, " "), result.getStdout(), result.getStderr());
+ }
}
return result;
}
- /**
- * InteractivePasswordHandler is a {@link org.apache.ambari.server.utils.ShellCommandUtil.InteractiveHandler}
- * implementation that answers queries from kadmin or kdamin.local command for the admin and/or user
- * passwords.
- */
- protected static class InteractivePasswordHandler implements ShellCommandUtil.InteractiveHandler {
- /**
- * The queue of responses to return
- */
- private LinkedList<String> responses;
- private Queue<String> currentResponses;
-
- /**
- * Constructor.
- *
- * @param adminPassword the KDC administrator's password (optional)
- * @param userPassword the user's password (optional)
- */
- public InteractivePasswordHandler(String adminPassword, String userPassword) {
- responses = new LinkedList<>();
-
- if (adminPassword != null) {
- responses.offer(adminPassword);
- }
+ @Override
+ protected String[] getKinitCommand(String executableKinit, PrincipalKeyCredential credentials, String credentialsCache) {
+ // kinit -c <path> -S kadmin/`hostname -f` <principal>
+ return new String[]{
+ executableKinit,
+ "-c",
+ credentialsCache,
+ "-S",
+ String.format("kadmin/%s", getAdminServerHost()),
+ credentials.getPrincipal()
+ };
+ }
- if (userPassword != null) {
- responses.offer(userPassword);
- responses.offer(userPassword); // Add a 2nd time for the password "confirmation" request
+ @Override
+ protected void exportKeytabFile(String principal, String keytabFileDestinationPath, Set<EncryptionType> keyEncryptionTypes) throws KerberosOperationException {
+ String encryptionTypeSpec = null;
+ if (!CollectionUtils.isEmpty(keyEncryptionTypes)) {
+ StringBuilder encryptionTypeSpecBuilder = new StringBuilder();
+ for (EncryptionType encryptionType : keyEncryptionTypes) {
+ if (encryptionTypeSpecBuilder.length() > 0) {
+ encryptionTypeSpecBuilder.append(',');
+ }
+ encryptionTypeSpecBuilder.append(encryptionType.getName());
+ encryptionTypeSpecBuilder.append(":normal");
}
- currentResponses = new LinkedList<>(responses);
+ encryptionTypeSpec = encryptionTypeSpecBuilder.toString();
}
- @Override
- public boolean done() {
- return currentResponses.size() == 0;
- }
+ String query = (StringUtils.isEmpty(encryptionTypeSpec))
+ ? String.format("xst -k \"%s\" %s", keytabFileDestinationPath, principal)
+ : String.format("xst -k \"%s\" -e %s %s", keytabFileDestinationPath, encryptionTypeSpec, principal);
- @Override
- public String getResponse(String query) {
- return currentResponses.poll();
- }
+ ShellCommandUtil.Result result = invokeKAdmin(query);
- @Override
- public void start() {
- currentResponses = new LinkedList<>(responses);
+ if (!result.isSuccessful()) {
+ String message = String.format("Failed to export the keytab file for %s:\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",
+ principal, result.getExitCode(), result.getStdout(), result.getStderr());
+ LOG.warn(message);
+ throw new KerberosOperationException(message);
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
index e1f8419..b9381b4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
@@ -107,7 +107,7 @@ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosS
Map<String, Map<String, String>> configurations = kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor, false, false);
processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory,
- configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore, false);
+ configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore);
// Add auth-to-local configurations to the set of changes
Map<String, Set<String>> authToLocalProperties = kerberosHelper.translateConfigurationSpecifications(kerberosDescriptor.getAllAuthToLocalProperties());
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
index 335451f..671ad95 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
@@ -119,7 +119,7 @@ public class PrepareEnableKerberosServerAction extends PrepareKerberosIdentities
Map<String, Map<String, String>> configurations = kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor, false, false);
processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory,
- configurations, kerberosConfigurations, true, propertiesToIgnore, false);
+ configurations, kerberosConfigurations, true, propertiesToIgnore);
// Calculate the set of configurations to update and replace any variables
// using the previously calculated Map of configurations for the host.
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
index 038d1b5..83a2106 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
@@ -30,6 +30,8 @@ import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.controller.RootComponent;
+import org.apache.ambari.server.controller.RootService;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.ServiceComponentHost;
import org.apache.ambari.server.state.kerberos.KerberosComponentDescriptor;
@@ -110,7 +112,8 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
if (serviceComponentFilter != null) {
// If we are including the Ambari identity; then ensure that if a service/component filter is set,
// it contains the AMBARI/AMBARI_SERVER component; else do not include the Ambari service identity.
- includeAmbariIdentity &= (serviceComponentFilter.get("AMBARI") != null) && serviceComponentFilter.get("AMBARI").contains("AMBARI_SERVER");
+ includeAmbariIdentity &= (serviceComponentFilter.get(RootService.AMBARI.name()) != null)
+ && serviceComponentFilter.get(RootService.AMBARI.name()).contains(RootComponent.AMBARI_SERVER.name());
if((operationType != OperationType.DEFAULT)) {
// Update the identity filter, if necessary
@@ -123,8 +126,7 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
Map<String, Map<String, String>> configurations = kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor, false, false);
processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory,
- configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore,
- hostFilter != null);
+ configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore);
kerberosHelper.applyStackAdvisorUpdates(cluster, services, configurations, kerberosConfigurations,
propertiesToIgnore, propertiesToRemove, true);
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
new file mode 100644
index 0000000..17e484a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
@@ -0,0 +1,257 @@
+/*
+ * 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.serveraction.kerberos.stageutils;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.state.kerberos.VariableReplacementHelper;
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Class that represents keytab. Contains principals that mapped to host.
+ * Same keytab can have different set of principals on different hosts.
+ */
+// TODO This class need to replace {@link org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFile}
+// TODO and all related structures and become main item that {@link org.apache.ambari.server.serveraction.kerberos.KerberosServerAction}
+// TODO operates with instead of identity records.
+public class ResolvedKerberosKeytab {
+
+ private String ownerName = null;
+ private String ownerAccess = null;
+ private String groupName = null;
+ private String groupAccess = null;
+ private String file = null;
+ private Set<Pair<Long, Pair<String, String>>> mappedPrincipals = null;
+ private boolean isAmbariServerKeytab = false;
+ private boolean mustWriteAmbariJaasFile = false;
+
+ public ResolvedKerberosKeytab(
+ String file,
+ String ownerName,
+ String ownerAccess,
+ String groupName,
+ String groupAccess,
+ Set<Pair<Long, Pair<String, String>>> mappedPrincipals,
+ boolean isAmbariServerKeytab,
+ boolean writeAmbariJaasFile
+ ) {
+ this.ownerName = ownerName;
+ this.ownerAccess = ownerAccess;
+ this.groupName = groupName;
+ this.groupAccess = groupAccess;
+ this.file = file;
+ this.mappedPrincipals = mappedPrincipals;
+ this.isAmbariServerKeytab = isAmbariServerKeytab;
+ this.mustWriteAmbariJaasFile = writeAmbariJaasFile;
+ }
+
+ /**
+ * Gets the path to the keytab file
+ * <p/>
+ * The value may include variable placeholders to be replaced as needed
+ * <ul>
+ * <li>
+ * ${variable} placeholders are replaced on the server - see
+ * {@link VariableReplacementHelper#replaceVariables(String, Map)}
+ * </li>
+ * </ul>
+ *
+ * @return a String declaring the keytab file's absolute path
+ * @see VariableReplacementHelper#replaceVariables(String, Map)
+ */
+ public String getFile() {
+ return file;
+ }
+
+ /**
+ * Sets the path to the keytab file
+ *
+ * @param file a String declaring this keytab's file path
+ * @see #getFile()
+ */
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ /**
+ * Gets the local username to set as the owner of the keytab file
+ *
+ * @return a String declaring the name of the user to own the keytab file
+ */
+ public String getOwnerName() {
+ return ownerName;
+ }
+
+ /**
+ * Sets the local username to set as the owner of the keytab file
+ *
+ * @param name a String declaring the name of the user to own the keytab file
+ */
+ public void setOwnerName(String name) {
+ this.ownerName = name;
+ }
+
+ /**
+ * Gets the access permissions that should be set on the keytab file related to the file's owner
+ *
+ * @return a String declaring the access permissions that should be set on the keytab file related
+ * to the file's owner
+ * @see #ownerAccess
+ */
+ public String getOwnerAccess() {
+ return ownerAccess;
+ }
+
+ /**
+ * Sets the access permissions that should be set on the keytab file related to the file's owner
+ *
+ * @param access a String declaring the access permissions that should be set on the keytab file
+ * related to the file's owner
+ * @see #ownerAccess
+ */
+ public void setOwnerAccess(String access) {
+ this.ownerAccess = access;
+ }
+
+ /**
+ * Gets the local group name to set as the group owner of the keytab file
+ *
+ * @return a String declaring the name of the group to own the keytab file
+ */
+ public String getGroupName() {
+ return groupName;
+ }
+
+ /**
+ * Sets the local group name to set as the group owner of the keytab file
+ *
+ * @param name a String declaring the name of the group to own the keytab file
+ */
+ public void setGroupName(String name) {
+ this.groupName = name;
+ }
+
+ /**
+ * Gets the access permissions that should be set on the keytab file related to the file's group
+ *
+ * @return a String declaring the access permissions that should be set on the keytab file related
+ * to the file's group
+ * @see #groupAccess
+ */
+ public String getGroupAccess() {
+ return groupAccess;
+ }
+
+ /**
+ * Sets the access permissions that should be set on the keytab file related to the file's group
+ *
+ * @param access a String declaring the access permissions that should be set on the keytab file
+ * related to the file's group
+ * @see #groupAccess
+ */
+ public void setGroupAccess(String access) {
+ this.groupAccess = access;
+ }
+
+ /**
+ * Gets evaluated host-to-principal set associated with given keytab.
+ *
+ * @return a Set with mappedPrincipals associated with given keytab
+ */
+ public Set<Pair<Long, Pair<String, String>>> getMappedPrincipals() {
+ return mappedPrincipals;
+ }
+
+ /**
+ * Sets evaluated host-to-principal set associated with given keytab.
+ *
+ * @param mappedPrincipals a Map with host-to-principal mapping associated with given keytab
+ */
+ public void setMappedPrincipals(Set<Pair<Long, Pair<String, String>>> mappedPrincipals) {
+ this.mappedPrincipals = mappedPrincipals;
+ }
+
+ /**
+ * Gets set of hosts associated with given keytab.
+ *
+ * @return a Set with hosts
+ */
+ public Set<Long> getHosts() {
+ ImmutableSet.Builder<Long> builder = ImmutableSet.builder();
+ for (Pair<Long, Pair<String, String>> principal : getMappedPrincipals()) {
+ if (principal.getLeft() != null) {
+ builder.add(principal.getLeft());
+ }
+ }
+ return builder.build();
+ }
+
+ /**
+ * Gets a set of principals associated with given keytab.
+ *
+ * @return a Set of principals
+ */
+ public Set<Pair<String, String>> getPrincipals() {
+ ImmutableSet.Builder<Pair<String, String>> builder = ImmutableSet.builder();
+ for (Pair<Long, Pair<String, String>> principal : getMappedPrincipals()) {
+ builder.add(principal.getRight());
+ }
+ return builder.build();
+ }
+
+ /**
+ * Indicates if given keytab is Ambari Server keytab and can be distributed to host with Ambari Server side action.
+ *
+ * @return true, if given keytab is Ambari Server keytab.
+ */
+ public boolean isAmbariServerKeytab() {
+ return isAmbariServerKeytab;
+ }
+
+ /**
+ * Sets flag to indicate if given keytab is Ambari Server keytab and can be distributed to host with Ambari Server
+ * side action.
+ *
+ * @param isAmbariServerKeytab flag value
+ */
+ public void setAmbariServerKeytab(boolean isAmbariServerKeytab) {
+ this.isAmbariServerKeytab = isAmbariServerKeytab;
+ }
+
+ /**
+ * Indicates if this keytab must be written to Ambari Server jaas file.
+ *
+ * @return true, if this keytab must be written to Ambari Server jaas file.
+ */
+ public boolean isMustWriteAmbariJaasFile() {
+ return mustWriteAmbariJaasFile;
+ }
+
+ /**
+ * Sets flag to indicate if this keytab must be written to Ambari Server jaas file.
+ *
+ * @param mustWriteAmbariJaasFile flag value
+ */
+ public void setMustWriteAmbariJaasFile(boolean mustWriteAmbariJaasFile) {
+ this.mustWriteAmbariJaasFile = mustWriteAmbariJaasFile;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureAction.java
new file mode 100644
index 0000000..ad031c8
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureAction.java
@@ -0,0 +1,164 @@
+/*
+ * 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.serveraction.upgrades;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ConfigurationRequest;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.DesiredConfig;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.UpgradeContext;
+import org.apache.ambari.server.state.stack.upgrade.CreateAndConfigureTask;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+
+/**
+ * The {@link CreateAndConfigureAction} is used to alter a configuration property during
+ * an upgrade. It also creates the config type if it does not exist as a desired config for the cluster.
+ * It will only produce a new configuration if an actual change is
+ * occuring. For some configure tasks, the value is already at the desired
+ * property or the conditions of the task are not met. In these cases, a new
+ * configuration will not be created. This task can perform any of the following
+ * actions in a single declaration:
+ * <ul>
+ * <li>Copy a configuration to a new property key, optionally setting a default
+ * if the original property did not exist</li>
+ * <li>Copy a configuration to a new property key from one configuration type to
+ * another, optionally setting a default if the original property did not exist</li>
+ * <li>Rename a configuration, optionally setting a default if the original
+ * property did not exist</li>
+ * <li>Delete a configuration property</li>
+ * <li>Set a configuration property</li>
+ * <li>Conditionally set a configuration property based on another configuration
+ * property value</li>
+ * </ul>
+ */
+public class CreateAndConfigureAction extends ConfigureAction {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CreateAndConfigureAction.class);
+
+ /**
+ * Used to lookup the cluster.
+ */
+ @Inject
+ private Clusters m_clusters;
+
+ /**
+ * Used to update the configuration properties.
+ */
+ @Inject
+ private AmbariManagementController m_controller;
+
+ /**
+ * Used to assist in the creation of a {@link ConfigurationRequest} to update
+ * configuration values.
+ */
+ @Inject
+ private ConfigHelper m_configHelper;
+
+
+ @Override
+ public CommandReport execute(
+ ConcurrentMap<String, Object> requestSharedDataContext)
+ throws AmbariException, InterruptedException {
+
+ LOG.info("Create and Configure...");
+
+ Map<String,String> commandParameters = getCommandParameters();
+ if( null == commandParameters || commandParameters.isEmpty() ){
+ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "",
+ "Unable to change configuration values without command parameters");
+ }
+
+ String clusterName = commandParameters.get("clusterName");
+ Cluster cluster = m_clusters.getCluster(clusterName);
+ UpgradeContext upgradeContext = getUpgradeContext(cluster);
+
+ Direction direction = upgradeContext.getDirection();
+ if (direction == Direction.DOWNGRADE) {
+ return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", "", "Skip changing configuration values for downgrade");
+ }
+
+ String configType = commandParameters.get(CreateAndConfigureTask.PARAMETER_CONFIG_TYPE);
+ String serviceName = cluster.getServiceByConfigType(configType).getName();
+
+ if (StringUtils.isBlank(serviceName)) {
+ serviceName = commandParameters.get(CreateAndConfigureTask.PARAMETER_ASSOCIATED_SERVICE);
+ }
+
+ RepositoryVersionEntity sourceRepoVersion = upgradeContext.getSourceRepositoryVersion(serviceName);
+ RepositoryVersionEntity targetRepoVersion = upgradeContext.getTargetRepositoryVersion(serviceName);
+ StackId sourceStackId = sourceRepoVersion.getStackId();
+ StackId targetStackId = targetRepoVersion.getStackId();
+
+ if (!sourceStackId.equals(targetStackId)){
+ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "",
+ "Unable to change configuration values across stacks. Use regular config task type instead.");
+ }
+
+ Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
+ DesiredConfig desiredConfig = desiredConfigs.get(configType);
+ if (desiredConfig == null) {
+ LOG.info(String.format("Could not find desired config type with name %s. Create it with default values.", configType));
+
+ // populate a map with default configurations from the new stack
+ Map<String, Map<String, String>> newServiceDefaultConfigsByType = m_configHelper.getDefaultProperties(
+ targetStackId, serviceName);
+
+ if (!newServiceDefaultConfigsByType.containsKey(configType)){
+ String error = String.format("%s in %s does not contain configuration type %s", serviceName, targetStackId.getStackId(), configType);
+ LOG.error(error);
+ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", error);
+ }
+
+ Map<String, String> defaultConfigsForType = newServiceDefaultConfigsByType.get(configType);
+ // Remove any property for the new config type whose value is NULL
+ Iterator<Map.Entry<String, String>> iter = defaultConfigsForType.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry<String, String> entry = iter.next();
+ if (entry.getValue() == null) {
+ iter.remove();
+ }
+ }
+
+ String serviceVersionNote = String.format("%s %s %s", direction.getText(true),
+ direction.getPreposition(), upgradeContext.getRepositoryVersion().getVersion());
+
+ m_configHelper.createConfigType(cluster, targetStackId,
+ m_controller,
+ configType, defaultConfigsForType,
+ m_controller.getAuthName(), serviceVersionNote);
+ }
+
+ return super.execute(requestSharedDataContext);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/PreconfigureKerberosAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/PreconfigureKerberosAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/PreconfigureKerberosAction.java
index 02cb70a..36b0491 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/PreconfigureKerberosAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/PreconfigureKerberosAction.java
@@ -38,8 +38,14 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.orm.dao.HostDAO;
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
+import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
+import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
+import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.serveraction.kerberos.PreconfigureServiceType;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.ConfigHelper;
import org.apache.ambari.server.state.Host;
@@ -56,6 +62,7 @@ import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
import org.apache.ambari.server.state.kerberos.VariableReplacementHelper;
import org.apache.ambari.server.state.stack.upgrade.Direction;
+import org.apache.ambari.server.utils.StageUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
@@ -82,6 +89,18 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
@Inject
private VariableReplacementHelper variableReplacementHelper;
+ @Inject
+ private HostDAO hostDAO;
+
+ @Inject
+ private KerberosKeytabDAO kerberosKeytabDAO;
+
+ @Inject
+ KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
+
+ @Inject
+ KerberosPrincipalDAO kerberosPrincipalDAO;
+
@Override
public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException {
Map<String, String> commandParameters = getCommandParameters();
@@ -131,7 +150,7 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
}
}
- processServiceComponentHosts(cluster, kerberosDescriptor, configurations, kerberosConfigurations, propertiesToIgnore);
+ processServiceComponentHosts(cluster, kerberosDescriptor, configurations, kerberosConfigurations, propertiesToIgnore, getDefaultRealm(configurations));
// Calculate the set of configurations to update and replace any variables
// using the previously calculated Map of configurations for the host.
@@ -280,7 +299,7 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
private void processServiceComponentHosts(Cluster cluster, KerberosDescriptor kerberosDescriptor,
Map<String, Map<String, String>> currentConfigurations,
Map<String, Map<String, String>> kerberosConfigurations,
- Map<String, Set<String>> propertiesToBeIgnored)
+ Map<String, Set<String>> propertiesToBeIgnored, String realm)
throws AmbariException {
Collection<Host> hosts = cluster.getHosts();
@@ -292,7 +311,7 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
try {
Map<String, Set<String>> propertiesToIgnore = null;
-
+ HashMap<String, ResolvedKerberosKeytab> resolvedKeytabs = new HashMap<>();
for (Host host : hosts) {
// Iterate over the components installed on the current host to get the service and
// component-level Kerberos descriptors in order to determine which principals,
@@ -323,7 +342,8 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
// Add service-level principals (and keytabs)
kerberosHelper.addIdentities(null, serviceIdentities,
- null, hostName, serviceName, componentName, kerberosConfigurations, currentConfigurations, false);
+ null, hostName, host.getHostId(), serviceName, componentName, kerberosConfigurations, currentConfigurations,
+ resolvedKeytabs, realm);
propertiesToIgnore = gatherPropertiesToIgnore(serviceIdentities, propertiesToIgnore);
KerberosComponentDescriptor componentDescriptor = serviceDescriptor.getComponent(componentName);
@@ -338,7 +358,8 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
// Add component-level principals (and keytabs)
kerberosHelper.addIdentities(null, componentIdentities,
- null, hostName, serviceName, componentName, kerberosConfigurations, currentConfigurations, false);
+ null, hostName, host.getHostId(), serviceName, componentName, kerberosConfigurations, currentConfigurations,
+ resolvedKeytabs,realm);
propertiesToIgnore = gatherPropertiesToIgnore(componentIdentities, propertiesToIgnore);
}
}
@@ -359,7 +380,8 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
List<KerberosIdentityDescriptor> componentIdentities = Collections.singletonList(identity);
kerberosHelper.addIdentities(null, componentIdentities,
- null, KerberosHelper.AMBARI_SERVER_HOST_NAME, "AMBARI", componentName, kerberosConfigurations, currentConfigurations, false);
+ null, KerberosHelper.AMBARI_SERVER_HOST_NAME, ambariServerHostID(), "AMBARI", componentName, kerberosConfigurations, currentConfigurations,
+ resolvedKeytabs, realm);
propertiesToIgnore = gatherPropertiesToIgnore(componentIdentities, propertiesToIgnore);
}
}
@@ -367,6 +389,11 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
if ((propertiesToBeIgnored != null) && (propertiesToIgnore != null)) {
propertiesToBeIgnored.putAll(propertiesToIgnore);
}
+
+ // create database records for keytabs that must be presented on cluster
+ for (ResolvedKerberosKeytab keytab : resolvedKeytabs.values()) {
+ kerberosHelper.processResolvedKeytab(keytab);
+ }
} catch (IOException e) {
throw new AmbariException(e.getMessage(), e);
}
@@ -582,5 +609,14 @@ public class PreconfigureKerberosAction extends AbstractUpgradeServerAction {
}
}
}
+
+ protected Long ambariServerHostID(){
+ String ambariServerHostName = StageUtils.getHostName();
+ HostEntity ambariServerHostEntity = hostDAO.findByName(ambariServerHostName);
+ return (ambariServerHostEntity == null)
+ ? null
+ : ambariServerHostEntity.getHostId();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/stack/RepoUtil.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/RepoUtil.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/RepoUtil.java
index 073fd82..eaddb2e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/RepoUtil.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/RepoUtil.java
@@ -191,6 +191,7 @@ public class RepoUtil {
re.setRepositoryId(repoInfo.getRepoId());
re.setDistribution(repoInfo.getDistribution());
re.setComponents(repoInfo.getComponents());
+ re.setTags(repoInfo.getTags());
return re;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
index f0d6c27..760d987 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceDirectory.java
@@ -93,6 +93,11 @@ public abstract class ServiceDirectory extends StackDefinitionDirectory {
protected File checksDir;
/**
+ * server side action directory path
+ */
+ protected File serverActionsDir;
+
+ /**
* service metainfo file object representation
*/
private ServiceMetainfoXml metaInfoXml;
@@ -118,6 +123,11 @@ public abstract class ServiceDirectory extends StackDefinitionDirectory {
protected static final String CHECKS_FOLDER_NAME = "checks";
/**
+ * Server actions directory name
+ */
+ protected static final String SERVER_ACTIONS_FOLDER_NAME = "server_actions";
+
+ /**
* service metainfo file name
*/
private static final String SERVICE_METAINFO_FILE_NAME = "metainfo.xml";
@@ -172,6 +182,15 @@ public abstract class ServiceDirectory extends StackDefinitionDirectory {
}
/**
+ * Obtain the server side actions directory path.
+ *
+ * @return server side actions directory path
+ */
+ public File getServerActionsDir() {
+ return serverActionsDir;
+ }
+
+ /**
* Obtain the metrics file.
*
* @return metrics file
@@ -303,6 +322,7 @@ public abstract class ServiceDirectory extends StackDefinitionDirectory {
calculatePackageDirectory(stack, service);
calculateUpgradesDirectory(stack, service);
calculateChecksDirectory(stack, service);
+ calculateServerActionsDirectory(stack, service);
}
/**
@@ -378,6 +398,15 @@ public abstract class ServiceDirectory extends StackDefinitionDirectory {
}
/**
+ * Sets the serverActionsDir if the dir exists and is not empty
+ * @param stack
+ * @param service
+ */
+ protected void calculateServerActionsDirectory(String stack, String service) {
+ serverActionsDir = resolveDirectory(SERVER_ACTIONS_FOLDER_NAME, stack, service);
+ }
+
+ /**
* Unmarshal the metainfo file into its object representation.
*
* @throws AmbariException if the metainfo file doesn't exist or
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
index ec4382e..ea992e1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
@@ -150,6 +150,7 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
serviceInfo.setServicePackageFolder(serviceDirectory.getPackageDir());
serviceInfo.setServiceUpgradesFolder(serviceDirectory.getUpgradesDir());
serviceInfo.setChecksFolder(serviceDirectory.getChecksDir());
+ serviceInfo.setServerActionsFolder(serviceDirectory.getServerActionsDir());
serviceInfo.setAdvisorFile(serviceDirectory.getAdvisorFile());
serviceInfo.setAdvisorName(serviceDirectory.getAdvisorName(serviceInfo.getName()));
@@ -270,6 +271,13 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
}
/*
+ * Use parent's server actions if the current one does not have any.
+ */
+ if (serviceInfo.getServerActionsFolder() == null) {
+ serviceInfo.setServerActionsFolder(parent.getServerActionsFolder());
+ }
+
+ /*
* If current stack version does not specify the credential store information
* for the service, then use parent definition.
*/
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/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 9b740d0..fc49a24 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
@@ -85,11 +85,6 @@ public class StackManager {
public static final String COMMON_SERVICES = "common-services";
/**
- * Prefix used for common stack hooks parent path string
- */
- public static final String DEFAULT_HOOKS_FOLDER = "stack-hooks";
-
- /**
* Prefix used for extension services parent path string
*/
public static final String EXTENSIONS = "extensions";
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index e999e24..4008c21 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -1508,22 +1508,22 @@ public class ConfigHelper {
}
/**
- * Compares values as double in case they are numbers.
- * @param actualValue
- * @param newValue
- * @return
+ * Checks for equality of parsed numbers if both values are numeric,
+ * otherwise using regular equality.
*/
- private boolean valuesAreEqual(String actualValue, String newValue) {
- boolean actualValueIsNumber = NumberUtils.isNumber(actualValue);
- boolean newValueIsNumber = NumberUtils.isNumber(newValue);
- if (actualValueIsNumber && newValueIsNumber) {
- Double ab = Double.parseDouble(actualValue);
- Double bb = Double.parseDouble(newValue);
- return ab.equals(bb);
- } else if (!actualValueIsNumber && !newValueIsNumber) {
- return actualValue.equals(newValue);
+ static boolean valuesAreEqual(String value1, String value2) { // exposed for unit test
+ if (NumberUtils.isNumber(value1) && NumberUtils.isNumber(value2)) {
+ try {
+ Number number1 = NumberUtils.createNumber(value1);
+ Number number2 = NumberUtils.createNumber(value2);
+ return Objects.equal(number1, number2) ||
+ number1.doubleValue() == number2.doubleValue();
+ } catch (NumberFormatException e) {
+ // fall back to regular equality
+ }
}
- return false;
+
+ return Objects.equal(value1, value2);
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryInfo.java
index 8ab1fe9..a7bbc1b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryInfo.java
@@ -18,7 +18,11 @@
package org.apache.ambari.server.state;
+import java.util.HashSet;
+import java.util.Set;
+
import org.apache.ambari.server.controller.RepositoryResponse;
+import org.apache.ambari.server.state.stack.RepoTag;
import com.google.common.base.Function;
import com.google.common.base.Objects;
@@ -36,6 +40,7 @@ public class RepositoryInfo {
private boolean repoSaved = false;
private boolean unique = false;
private boolean ambariManagedRepositories = true;
+ private Set<RepoTag> tags = new HashSet<>();
/**
* @return the baseUrl
@@ -207,7 +212,8 @@ public class RepositoryInfo {
public RepositoryResponse convertToResponse()
{
return new RepositoryResponse(getBaseUrl(), getOsType(), getRepoId(),
- getRepoName(), getDistribution(), getComponents(), getMirrorsList(), getDefaultBaseUrl());
+ getRepoName(), getDistribution(), getComponents(), getMirrorsList(), getDefaultBaseUrl(),
+ getTags());
}
/**
@@ -259,4 +265,19 @@ public class RepositoryInfo {
public void setAmbariManagedRepositories(boolean ambariManagedRepositories) {
this.ambariManagedRepositories = ambariManagedRepositories;
}
+
+ /**
+ * @return the tags for this repository
+ */
+ public Set<RepoTag> getTags() {
+ return tags;
+ }
+
+ /**
+ * @param repoTags the tags for this repository
+ */
+ public void setTags(Set<RepoTag> repoTags) {
+ tags = repoTags;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
index c6b187a..9dc77c1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
@@ -822,7 +822,7 @@ public class ServiceImpl implements Service {
List<Component> result = new ArrayList<>();
for (ServiceComponent component : getServiceComponents().values()) {
for (ServiceComponentHost host : component.getServiceComponentHosts().values()) {
- result.add(new Component(host.getHostName(), getName(), component.getName()));
+ result.add(new Component(host.getHostName(), getName(), component.getName(), host.getHost().getHostId()));
}
}
return result;
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/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 0e6e3c3..184be38 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
@@ -307,6 +307,12 @@ public class ServiceInfo implements Validable, Cloneable {
@XmlTransient
private File checksFolder;
+ /**
+ * Stores the path to the server actions folder which contains server actions jars for the given service.
+ */
+ @XmlTransient
+ private File serverActionsFolder;
+
public boolean isDeleted() {
return isDeleted;
}
@@ -833,6 +839,14 @@ public class ServiceInfo implements Validable, Cloneable {
this.checksFolder = checksFolder;
}
+ public File getServerActionsFolder() {
+ return serverActionsFolder;
+ }
+
+ public void setServerActionsFolder(File serverActionsFolder) {
+ this.serverActionsFolder = serverActionsFolder;
+ }
+
/**
* Exposes (and initializes on first use) map of os-specific details.
* @return map of OS specific details keyed by family
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
index 025015a..4f50a01 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
@@ -37,8 +37,8 @@ import org.apache.ambari.server.ClusterNotFoundException;
import org.apache.ambari.server.agent.ActionQueue;
import org.apache.ambari.server.agent.AgentCommand.AgentCommandType;
import org.apache.ambari.server.agent.AlertDefinitionCommand;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
+import org.apache.ambari.server.controller.RootComponent;
+import org.apache.ambari.server.controller.RootService;
import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
import org.apache.ambari.server.state.Cluster;
@@ -375,8 +375,8 @@ public class AlertDefinitionHash {
return affectedHosts;
}
- String ambariServiceName = Services.AMBARI.name();
- String agentComponentName = Components.AMBARI_AGENT.name();
+ String ambariServiceName = RootService.AMBARI.name();
+ String agentComponentName = RootComponent.AMBARI_AGENT.name();
// intercept host agent alerts; they affect all hosts
if (ambariServiceName.equals(definitionServiceName)
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index e3b5d6e..0b38b36 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -60,7 +60,7 @@ import org.apache.ambari.server.controller.AmbariSessionManager;
import org.apache.ambari.server.controller.ClusterResponse;
import org.apache.ambari.server.controller.ConfigurationResponse;
import org.apache.ambari.server.controller.MaintenanceStateHelper;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
+import org.apache.ambari.server.controller.RootService;
import org.apache.ambari.server.controller.ServiceComponentHostResponse;
import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
import org.apache.ambari.server.events.AmbariEvent.AmbariEventType;
@@ -2568,7 +2568,7 @@ public class ClusterImpl implements Cluster {
// server-side events either don't have a service name or are AMBARI;
// either way they are not handled by this method since it expects a
// real service and component
- if (StringUtils.isBlank(serviceName) || Services.AMBARI.name().equals(serviceName)) {
+ if (StringUtils.isBlank(serviceName) || RootService.AMBARI.name().equals(serviceName)) {
continue;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ClusterVersionSummary.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ClusterVersionSummary.java b/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ClusterVersionSummary.java
index e9d9920..5486ecd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ClusterVersionSummary.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ClusterVersionSummary.java
@@ -24,11 +24,14 @@ import java.util.Set;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
/**
* For a version, collects summary information for a cluster.
*/
public class ClusterVersionSummary {
+ @SerializedName("services")
@JsonProperty("services")
private Map<String, ServiceVersionSummary> m_services;
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ServiceVersionSummary.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ServiceVersionSummary.java b/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ServiceVersionSummary.java
index 29505c8..d87caef 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ServiceVersionSummary.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/repository/ServiceVersionSummary.java
@@ -20,25 +20,26 @@ package org.apache.ambari.server.state.repository;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
/**
* Used to hold information about Service's ability to upgrade for a repository version.
*/
public class ServiceVersionSummary {
- @JsonProperty("display_name")
- private String m_displayName;
-
+ @SerializedName("version")
@JsonProperty("version")
private String m_version;
+ @SerializedName("release_version")
@JsonProperty("release_version")
private String m_releaseVersion;
+ @SerializedName("upgrade")
@JsonProperty("upgrade")
private boolean m_upgrade = false;
- ServiceVersionSummary(String displayName) {
- m_displayName = displayName;
+ ServiceVersionSummary() {
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java
index 099215e..7680ee1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java
@@ -314,7 +314,7 @@ public class VersionDefinitionXml {
continue;
}
- ServiceVersionSummary summary = new ServiceVersionSummary(service.getDisplayName());
+ ServiceVersionSummary summary = new ServiceVersionSummary();
summaries.put(service.getName(), summary);
String serviceVersion = service.getDesiredRepositoryVersion().getVersion();
@@ -322,13 +322,26 @@ public class VersionDefinitionXml {
// !!! currently only one version is supported (unique service names)
ManifestService manifest = manifests.get(serviceName);
- summary.setVersions(manifest.version, StringUtils.isEmpty(manifest.releaseVersion) ?
- release.version : manifest.releaseVersion);
+ final String versionToCompare;
+ final String summaryReleaseVersion;
+ if (StringUtils.isEmpty(manifest.releaseVersion)) {
+ versionToCompare = release.getFullVersion();
+ summaryReleaseVersion = release.version;
+ } else {
+ versionToCompare = manifest.releaseVersion;
+ summaryReleaseVersion = manifest.releaseVersion;
+ }
+
+ summary.setVersions(manifest.version, summaryReleaseVersion);
- // !!! installed service already meets the release version, then nothing to upgrade
- // !!! TODO should this be using the release compatible-with field?
- if (VersionUtils.compareVersions(summary.getReleaseVersion(), serviceVersion, 4) > 0) {
+ if (RepositoryType.STANDARD == release.repositoryType) {
summary.setUpgrade(true);
+ } else {
+ // !!! installed service already meets the release version, then nothing to upgrade
+ // !!! TODO should this be using the release compatible-with field?
+ if (VersionUtils.compareVersionsWithBuild(versionToCompare, serviceVersion, 4) > 0) {
+ summary.setUpgrade(true);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
index d3237a9..305f693 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AmbariServerAlertService.java
@@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.ambari.server.AmbariService;
import org.apache.ambari.server.alerts.AlertRunnable;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
+import org.apache.ambari.server.controller.RootComponent;
import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
import org.apache.ambari.server.state.Cluster;
@@ -133,7 +133,7 @@ public class AmbariServerAlertService extends AbstractScheduledService {
/**
* {@inheritDoc}
* <p/>
- * Compares all known {@link Components#AMBARI_SERVER} alerts with those that
+ * Compares all known {@link RootComponent#AMBARI_SERVER} alerts with those that
* are scheduled. If any are not scheduled or have their intervals changed,
* then reschedule those.
*/
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/services/MetricsRetrievalService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/MetricsRetrievalService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/MetricsRetrievalService.java
index 510e706..7e5aad1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/MetricsRetrievalService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/MetricsRetrievalService.java
@@ -101,7 +101,7 @@ public class MetricsRetrievalService extends AbstractService {
/**
* Logger.
*/
- protected final static Logger LOG = LoggerFactory.getLogger(MetricsRetrievalService.class);
+ private static final Logger LOG = LoggerFactory.getLogger(MetricsRetrievalService.class);
/**
* The timeout for exceptions which are caught and then cached to prevent log
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/OsFamily.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/OsFamily.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/OsFamily.java
index c0483e8..b84de01 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/OsFamily.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/OsFamily.java
@@ -53,7 +53,7 @@ public class OsFamily {
private final String OS_VERSION = "versions";
private final String LOAD_CONFIG_MSG = "Could not load OS family definition from %s file";
private final String FILE_NAME = "os_family.json";
- private final Logger LOG = LoggerFactory.getLogger(OsFamily.class);
+ private static final Logger LOG = LoggerFactory.getLogger(OsFamily.class);
private Map<String, JsonOsFamilyEntry> osMap = null;
private JsonOsFamilyRoot jsonOsFamily = null;
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoTag.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoTag.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoTag.java
new file mode 100644
index 0000000..08a2635
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepoTag.java
@@ -0,0 +1,34 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlEnum;
+
+/**
+ * A Repo tag is a way to allow Ambari to place logic surrounding repository details.
+ * This is used instead of random strings to tightly control how tags are used.
+ */
+@XmlEnum
+public enum RepoTag {
+
+ /**
+ * The repository may contain GPL-Licensed software
+ */
+ GPL
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
index c2209bb..ccb25e8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/RepositoryXml.java
@@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@@ -150,6 +151,10 @@ public class RepositoryXml implements Validable{
private String components = null;
private boolean unique = false;
+ @XmlElementWrapper(name="tags")
+ @XmlElement(name="tag")
+ private Set<RepoTag> tags = new HashSet<>();
+
private Repo() {
}
@@ -201,6 +206,13 @@ public class RepositoryXml implements Validable{
public void setUnique(boolean unique) {
this.unique = unique;
}
+
+ /**
+ * @return the repo tags
+ */
+ public Set<RepoTag> getTags() {
+ return tags;
+ }
}
/**
@@ -224,6 +236,7 @@ public class RepositoryXml implements Validable{
ri.setDistribution(r.getDistribution());
ri.setComponents(r.getComponents());
ri.setUnique(r.isUnique());
+ ri.setTags(r.tags);
repos.add(ri);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
index 7c32f37..7fb04f5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/UpgradePack.java
@@ -38,6 +38,7 @@ import javax.xml.bind.annotation.XmlValue;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.state.stack.upgrade.ClusterGrouping;
import org.apache.ambari.server.state.stack.upgrade.ConfigureTask;
+import org.apache.ambari.server.state.stack.upgrade.CreateAndConfigureTask;
import org.apache.ambari.server.state.stack.upgrade.Direction;
import org.apache.ambari.server.state.stack.upgrade.Grouping;
import org.apache.ambari.server.state.stack.upgrade.ServiceCheckGrouping;
@@ -600,6 +601,8 @@ public class UpgradePack {
for (Task task : tasks) {
if (Task.Type.CONFIGURE == task.getType()) {
((ConfigureTask) task).associatedService = service;
+ } else if (Task.Type.CREATE_AND_CONFIGURE == task.getType()) {
+ ((CreateAndConfigureTask) task).associatedService = service;
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java
index 5bc3d8f..c9219d3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java
@@ -135,6 +135,8 @@ public class ClusterGrouping extends Grouping {
void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
if (task.getType().equals(Task.Type.CONFIGURE) && StringUtils.isNotEmpty(service)) {
((ConfigureTask) task).associatedService = service;
+ } else if (task.getType().equals(Task.Type.CREATE_AND_CONFIGURE) && StringUtils.isNotEmpty(service)) {
+ ((CreateAndConfigureTask) task).associatedService = service;
}
}