This is an automated email from the ASF dual-hosted git repository.
rlevas pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 249af2b [AMBARI-23129] Multiple issues while executing Ambari server
upgrade to Ambari 2.7.0 (#608)
249af2b is described below
commit 249af2b0cc03d57b05ce3a259524b16e870363e3
Author: Robert Levas <[email protected]>
AuthorDate: Sat Mar 10 16:35:14 2018 -0500
[AMBARI-23129] Multiple issues while executing Ambari server upgrade to
Ambari 2.7.0 (#608)
* [AMBARI-23129] Multiple issues while executing Ambari server upgrade to
Ambari 2.7.0
* [AMBARI-23129] Multiple issues while executing Ambari server upgrade to
Ambari 2.7.0
---
.../ambari/server/controller/AmbariServer.java | 4 +-
.../org/apache/ambari/server/orm/DBAccessor.java | 34 ++-
.../apache/ambari/server/orm/DBAccessorImpl.java | 174 ++++++++++++---
.../ambari/server/orm/GuiceJpaInitializer.java | 29 ++-
.../security/ldap/AmbariLdapDataPopulator.java | 29 ++-
.../ambari/server/state/cluster/ClustersImpl.java | 234 +++++++++++++++------
.../ambari/server/upgrade/SchemaUpgradeHelper.java | 13 +-
.../ambari/server/upgrade/UpgradeCatalog270.java | 234 +++++++++++++++++++++
.../ambari/server/orm/DBAccessorImplTest.java | 70 ++++++
.../security/ldap/AmbariLdapDataPopulatorTest.java | 1 -
.../server/upgrade/UpgradeCatalog270Test.java | 139 ++++++++++++
.../apache/ambari/server/upgrade/UpgradeTest.java | 4 -
12 files changed, 853 insertions(+), 112 deletions(-)
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 1651f1a..9eedd26 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -1077,7 +1077,9 @@ public class AmbariServer {
setupProxyAuth();
- injector.getInstance(GuiceJpaInitializer.class);
+ // Start and Initialize JPA
+ GuiceJpaInitializer jpaInitializer =
injector.getInstance(GuiceJpaInitializer.class);
+ jpaInitializer.setInitialized(); // This must be called to alert Ambari
that JPA is initialized.
DatabaseConsistencyCheckHelper.checkDBVersionCompatible();
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
index f0431e9..731cf00 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
+import java.util.Map;
import org.apache.ambari.server.configuration.Configuration.DatabaseType;
import org.apache.commons.lang.builder.EqualsBuilder;
@@ -372,16 +373,33 @@ public interface DBAccessor {
* Execute select {@code columnName} from {@code tableName}
* where {@code columnNames} values = {@code values}
*
- * @param tableName
- * @param columnName
- * @param columnNames
- * @param values
- * @param ignoreFailure
- * @return
+ * @param tableName the table name
+ * @param columnName the name of the column with the data to select
+ * @param conditionColumnNames an array of column names to use in the where
clause
+ * @param conditionValues an array of value to pair with the column
names in conditionColumnNames
+ * @param ignoreFailure true to ignore failures executing the query;
false otherwise (errors building the query will be thrown, however)
+ * @return a list of integers
* @throws SQLException
*/
- List<Integer> getIntColumnValues(String tableName, String columnName,
String[] columnNames,
- String[] values, boolean ignoreFailure)
throws SQLException;
+ List<Integer> getIntColumnValues(String tableName, String columnName,
String[] conditionColumnNames,
+ String[] conditionValues, boolean
ignoreFailure) throws SQLException;
+
+ /**
+ * Execute select {@code keyColumnName}, {@code valueColumnName} from {@code
tableName}
+ * where {@code columnNames} values = {@code values}
+ *
+ * @param tableName the table name
+ * @param keyColumnName the name of the column with the key data to
select
+ * @param valueColumnName the name of the column with the value data to
select
+ * @param conditionColumnNames an array of column names to use in the where
clause
+ * @param conditionValues an array of value to pair with the column
names in conditionColumnNames
+ * @param ignoreFailure true to ignore failures executing the query;
false otherwise (errors building the query will be thrown, however)
+ * @return a map of key to values
+ * @throws SQLException
+ */
+ Map<Long, String> getKeyToStringColumnMap(String tableName, String
keyColumnName, String valueColumnName,
+ String[] conditionColumnNames,
String[] conditionValues,
+ boolean ignoreFailure) throws
SQLException;
/**
* Drop table from schema
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
index 3a42342..ed3f8f2 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
@@ -35,8 +35,10 @@ import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.ambari.server.configuration.Configuration;
@@ -1446,41 +1448,73 @@ public class DBAccessorImpl implements DBAccessor {
* {@inheritDoc}
*/
@Override
- public List<Integer> getIntColumnValues(String tableName, String columnName,
String[] ConditionColumnNames,
+ public List<Integer> getIntColumnValues(String tableName, String columnName,
String[] conditionColumnNames,
String[] values, boolean
ignoreFailure) throws SQLException {
+ return executeQuery(tableName, new String[]{columnName},
conditionColumnNames, values, ignoreFailure,
+ new ResultGetter<List<Integer>>() {
+ private List<Integer> results = new ArrayList<>();
- if (!tableExists(tableName)) {
- throw new IllegalArgumentException(String.format("%s table does not
exist", tableName));
- }
- if (!tableHasColumn(tableName, columnName)) {
- throw new IllegalArgumentException(String.format("%s table does not
contain %s column", tableName, columnName));
- }
- StringBuilder builder = new StringBuilder();
- builder.append("SELECT ").append(columnName).append(" FROM
").append(tableName);
- if (ConditionColumnNames != null && ConditionColumnNames.length > 0) {
- for (String name : ConditionColumnNames) {
- if (!tableHasColumn(tableName, name)) {
- throw new IllegalArgumentException(String.format("%s table does not
contain %s column", tableName, name));
- }
- }
- if (ConditionColumnNames.length != values.length) {
- throw new IllegalArgumentException("number of columns should be equal
to number of values");
- }
- builder.append(" WHERE
").append(ConditionColumnNames[0]).append("='").append(values[0]).append("'");
- for (int i = 1; i < ConditionColumnNames.length; i++) {
- builder.append(" AND
").append(ConditionColumnNames[i]).append("='").append(values[i]).append("'");
- }
- }
+ @Override
+ public void collect(ResultSet resultSet) throws SQLException {
+ results.add(resultSet.getInt(1));
+ }
- List<Integer> result = new ArrayList<>();
+ @Override
+ public List<Integer> getResult() {
+ return results;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Map<Long, String> getKeyToStringColumnMap(String tableName, String
keyColumnName, String valueColumnName,
+ String[] conditionColumnNames,
String[] values, boolean ignoreFailure) throws SQLException {
+ return executeQuery(tableName, new String[]{keyColumnName,
valueColumnName}, conditionColumnNames, values, ignoreFailure,
+ new ResultGetter<Map<Long, String>>() {
+ Map<Long, String> map = new HashMap<>();
+
+ @Override
+ public void collect(ResultSet resultSet) throws SQLException {
+ map.put(resultSet.getLong(1), resultSet.getString(2));
+ }
+
+ @Override
+ public Map<Long, String> getResult() {
+ return map;
+ }
+ });
+ }
+
+ /**
+ * Executes a query returning data as specified by the {@link ResultGetter}
implementation.
+ *
+ * @param tableName the table name
+ * @param requestedColumnNames an array of column names to select
+ * @param conditionColumnNames an array of column names to use in the where
clause
+ * @param conditionValues an array of value to pair with the column
names in conditionColumnNames
+ * @param ignoreFailure true to ignore failures executing the query;
false otherwise (errors building the query will be thrown, however)
+ * @param resultGetter a {@link ResultGetter} implementation used to
format the data into the expected return value
+ * @return the result from the resultGetter
+ * @throws SQLException
+ */
+ protected <T> T executeQuery(String tableName, String[] requestedColumnNames,
+ String[] conditionColumnNames, String[]
conditionValues,
+ boolean ignoreFailure, ResultGetter<T>
resultGetter) throws SQLException {
+
+ // Build the query...
+ String query = buildQuery(tableName, requestedColumnNames,
conditionColumnNames, conditionValues);
+
+ // Execute the query
Statement statement = getConnection().createStatement();
ResultSet resultSet = null;
- String query = builder.toString();
try {
resultSet = statement.executeQuery(query);
if (resultSet != null) {
while (resultSet.next()) {
- result.add(resultSet.getInt(1));
+ resultGetter.collect(resultSet);
}
}
} catch (SQLException e) {
@@ -1496,7 +1530,72 @@ public class DBAccessorImpl implements DBAccessor {
statement.close();
}
}
- return result;
+
+ return resultGetter.getResult();
+ }
+
+ /**
+ * Build a SELECT statement using the supplied table name, request columns
and conditional column/value pairs.
+ * <p>
+ * The conditional pairs are optional but multiple pairs will be ANDed
together.
+ * <p>
+ * Examples:
+ * <ul>
+ * <li>SELECT id FROM table1</li>
+ * <li>SELECT id FROM table1 WHERE name='value1'</li>
+ * <li>SELECT id FROM table1 WHERE name='value1' AND key='key1'</li>
+ * <li>SELECT id, name FROM table1 WHERE key='key1'</li>
+ * <li>SELECT id, name FROM table1 WHERE key='key1' AND allowed='1'</li>
+ * </ul>
+ *
+ * @param tableName the table name
+ * @param requestedColumnNames an array of column names to select
+ * @param conditionColumnNames an array of column names to use in the where
clause
+ * @param conditionValues an array of value to pair with the column
names in conditionColumnNames
+ * @return a query string
+ * @throws SQLException
+ */
+ protected String buildQuery(String tableName, String[] requestedColumnNames,
String[] conditionColumnNames, String[] conditionValues) throws SQLException {
+ if (!tableExists(tableName)) {
+ throw new IllegalArgumentException(String.format("%s table does not
exist", tableName));
+ }
+ StringBuilder builder = new StringBuilder();
+ builder.append("SELECT ");
+
+ // Append the requested column names:
+ if ((requestedColumnNames == null) || (requestedColumnNames.length == 0)) {
+ throw new IllegalArgumentException("no columns for the select have been
set");
+ }
+ for (String name : requestedColumnNames) {
+ if (!tableHasColumn(tableName, name)) {
+ throw new IllegalArgumentException(String.format("%s table does not
contain %s column", tableName, name));
+ }
+ }
+ builder.append(requestedColumnNames[0]);
+ for (int i = 1; i < requestedColumnNames.length; i++) {
+ builder.append(", ").append(requestedColumnNames[1]);
+ }
+
+ // Append the source table
+ builder.append(" FROM ").append(tableName);
+
+ // Add the WHERE clause using the conditionColumnNames and the
conditionValues
+ if (conditionColumnNames != null && conditionColumnNames.length > 0) {
+ for (String name : conditionColumnNames) {
+ if (!tableHasColumn(tableName, name)) {
+ throw new IllegalArgumentException(String.format("%s table does not
contain %s column", tableName, name));
+ }
+ }
+ if (conditionColumnNames.length != conditionValues.length) {
+ throw new IllegalArgumentException("number of columns should be equal
to number of values");
+ }
+ builder.append(" WHERE
").append(conditionColumnNames[0]).append("='").append(conditionValues[0]).append("'");
+ for (int i = 1; i < conditionColumnNames.length; i++) {
+ builder.append(" AND
").append(conditionColumnNames[i]).append("='").append(conditionValues[i]).append("'");
+ }
+ }
+
+ return builder.toString();
}
/**
@@ -1582,4 +1681,25 @@ public class DBAccessorImpl implements DBAccessor {
LOG.warn("{} table doesn't exists, skipping", tableName);
}
}
+
+ /**
+ * {@link ResultGetter} is an interface to implement to help compile results
+ * from a SQL query.
+ */
+ private interface ResultGetter<T> {
+ /**
+ * Collect results from the query's {@link ResultSet}
+ *
+ * @param resultSet the result set
+ * @throws SQLException
+ */
+ void collect(ResultSet resultSet) throws SQLException;
+
+ /**
+ * Return the compiled results in the expected data type
+ *
+ * @return the results
+ */
+ T getResult();
+ }
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java
b/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java
index 8947df0..c049c72 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/orm/GuiceJpaInitializer.java
@@ -22,16 +22,41 @@ import org.apache.ambari.server.events.JpaInitializedEvent;
import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import com.google.inject.persist.PersistService;
/**
- * This class needs to be instantiated with guice to initialize Guice-persist
+ * This class needs to be instantiated with Guice to initialize Guice-persist
*/
+@Singleton
public class GuiceJpaInitializer {
-
+
+ private final AmbariEventPublisher publisher;
+
+ /**
+ * GuiceJpaInitializer constructor.
+ * <p>
+ * Starts the JPA service and holds on to an {@link AmbariEventPublisher}
for future use.
+ *
+ * @param service the persist service
+ * @param publisher the Ambari event publisher
+ */
@Inject
public GuiceJpaInitializer(PersistService service, AmbariEventPublisher
publisher) {
+ this.publisher = publisher;
service.start();
+ }
+
+ /**
+ * Called to indicate that the JPA service is initialized and ready for use.
+ * <p>
+ * This means that the schema for the underlying database matches the JPA
entity objects expectations
+ * and the PersistService has been started.
+ * <p>
+ * A {@link JpaInitializedEvent} is published so that subscribers can
perform database-related tasks
+ * when the infrastructure is ready.
+ */
+ public void setInitialized() {
publisher.publish(new JpaInitializedEvent());
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
b/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
index 40bcd7f..121e7a6 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulator.java
@@ -105,14 +105,24 @@ public class AmbariLdapDataPopulator {
/**
* Construct an AmbariLdapDataPopulator.
*
- * @param configuration the Ambari configuration
- * @param users utility that provides access to Users
+ * @param configurationProvider the Ambari configuration
+ * @param users utility that provides access to Users
*/
@Inject
public AmbariLdapDataPopulator(Provider<AmbariLdapConfiguration>
configurationProvider, Users users) {
this.configurationProvider = configurationProvider;
this.users = users;
- this.ldapServerProperties = getConfiguration().getLdapServerProperties();
+ this.ldapServerProperties = null;
+ }
+
+ /**
+ * Load the initial LDAP configuration if the JPA infrastructure is
initialized.
+ */
+ synchronized private LdapServerProperties getLdapProperties() {
+ if (ldapServerProperties == null) {
+ ldapServerProperties = getConfiguration().getLdapServerProperties();
+ }
+ return ldapServerProperties;
}
/**
@@ -126,7 +136,7 @@ public class AmbariLdapDataPopulator {
}
try {
final LdapTemplate ldapTemplate = loadLdapTemplate();
- ldapTemplate.search(ldapServerProperties.getBaseDN(),
"uid=dummy_search", new AttributesMapper() {
+ ldapTemplate.search(getLdapProperties().getBaseDN(), "uid=dummy_search",
new AttributesMapper() {
@Override
public Object mapFromAttributes(Attributes arg0) throws
NamingException {
@@ -447,6 +457,7 @@ public class AmbariLdapDataPopulator {
* @return the set of LDAP groups for the given name
*/
protected Set<LdapGroupDto> getLdapGroups(String groupName) {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
Filter groupObjectFilter = new EqualsFilter(OBJECT_CLASS_ATTRIBUTE,
ldapServerProperties.getGroupObjectClass());
Filter groupNameFilter = new
LikeFilter(ldapServerProperties.getGroupNamingAttr(), groupName);
@@ -460,6 +471,7 @@ public class AmbariLdapDataPopulator {
* @return the set of LDAP users for the given name
*/
protected Set<LdapUserDto> getLdapUsers(String username) {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
Filter userObjectFilter = new EqualsFilter(OBJECT_CLASS_ATTRIBUTE,
ldapServerProperties.getUserObjectClass());
Filter userNameFilter = new
LikeFilter(ldapServerProperties.getUsernameAttribute(), username);
return getFilteredLdapUsers(ldapServerProperties.getBaseDN(),
userObjectFilter, userNameFilter);
@@ -472,6 +484,7 @@ public class AmbariLdapDataPopulator {
* @return the user for the given member attribute; null if not found
*/
protected LdapUserDto getLdapUserByMemberAttr(String memberAttributeValue) {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
Set<LdapUserDto> filteredLdapUsers;
memberAttributeValue = getUniqueIdByMemberPattern(memberAttributeValue,
@@ -504,6 +517,7 @@ public class AmbariLdapDataPopulator {
* @return the group for the given member attribute; null if not found
*/
protected LdapGroupDto getLdapGroupByMemberAttr(String memberAttributeValue)
{
+ LdapServerProperties ldapServerProperties = getLdapProperties();
Set<LdapGroupDto> filteredLdapGroups;
memberAttributeValue = getUniqueIdByMemberPattern(memberAttributeValue,
@@ -602,6 +616,7 @@ public class AmbariLdapDataPopulator {
* Determines that the member attribute can be used as a 'dn'
*/
protected boolean isMemberAttributeBaseDn(String memberAttributeValue) {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
Pattern pattern = Pattern.compile(String.format(IS_MEMBER_DN_REGEXP,
ldapServerProperties.getUsernameAttribute(),
ldapServerProperties.getGroupNamingAttr()));
return pattern.matcher(memberAttributeValue).find();
@@ -613,6 +628,7 @@ public class AmbariLdapDataPopulator {
* @return set of info about LDAP groups
*/
protected Set<LdapGroupDto> getExternalLdapGroupInfo() {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
EqualsFilter groupObjectFilter = new EqualsFilter(OBJECT_CLASS_ATTRIBUTE,
ldapServerProperties.getGroupObjectClass());
return getFilteredLdapGroups(ldapServerProperties.getBaseDN(),
groupObjectFilter);
@@ -620,6 +636,7 @@ public class AmbariLdapDataPopulator {
// get a filter based on the given member attribute
private Filter getMemberFilter(String memberAttributeValue) {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
String dnAttribute = ldapServerProperties.getDnAttribute();
return new OrFilter().or(new EqualsFilter(dnAttribute,
memberAttributeValue)).
@@ -637,6 +654,7 @@ public class AmbariLdapDataPopulator {
private Set<LdapGroupDto> getFilteredLdapGroups(String baseDn, Filter
filter) {
final Set<LdapGroupDto> groups = new HashSet<>();
final LdapTemplate ldapTemplate = loadLdapTemplate();
+ LdapServerProperties ldapServerProperties = getLdapProperties();
LOG.trace("LDAP Group Query - Base DN: '{}' ; Filter: '{}'", baseDn,
filter.encode());
ldapTemplate.search(baseDn, filter.encode(),
new LdapGroupContextMapper(groups, ldapServerProperties));
@@ -649,6 +667,7 @@ public class AmbariLdapDataPopulator {
* @return set of info about LDAP users
*/
protected Set<LdapUserDto> getExternalLdapUserInfo() {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
EqualsFilter userObjectFilter = new EqualsFilter(OBJECT_CLASS_ATTRIBUTE,
ldapServerProperties.getUserObjectClass());
return getFilteredLdapUsers(ldapServerProperties.getBaseDN(),
userObjectFilter);
@@ -665,6 +684,7 @@ public class AmbariLdapDataPopulator {
private Set<LdapUserDto> getFilteredLdapUsers(String baseDn, Filter filter) {
final Set<LdapUserDto> users = new HashSet<>();
final LdapTemplate ldapTemplate = loadLdapTemplate();
+ LdapServerProperties ldapServerProperties = getLdapProperties();
PagedResultsDirContextProcessor processor = createPagingProcessor();
SearchControls searchControls = new SearchControls();
searchControls.setReturningObjFlag(true);
@@ -740,6 +760,7 @@ public class AmbariLdapDataPopulator {
* @return LdapTemplate instance
*/
protected LdapTemplate loadLdapTemplate() {
+ LdapServerProperties ldapServerProperties = getLdapProperties();
final LdapServerProperties properties =
getConfiguration().getLdapServerProperties();
if (ldapTemplate == null || !properties.equals(ldapServerProperties)) {
LOG.info("Reloading properties");
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
index eadcc32..55ef12f 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
@@ -99,12 +99,12 @@ public class ClustersImpl implements Clusters {
private static final Logger LOG =
LoggerFactory.getLogger(ClustersImpl.class);
- private final ConcurrentHashMap<String, Cluster> clusters = new
ConcurrentHashMap<>();
- private final ConcurrentHashMap<Long, Cluster> clustersById = new
ConcurrentHashMap<>();
- private final ConcurrentHashMap<String, Host> hosts = new
ConcurrentHashMap<>();
- private final ConcurrentHashMap<Long, Host> hostsById = new
ConcurrentHashMap<>();
- private final ConcurrentHashMap<String, Set<Cluster>> hostClusterMap = new
ConcurrentHashMap<>();
- private final ConcurrentHashMap<String, Set<Host>> clusterHostMap = new
ConcurrentHashMap<>();
+ private ConcurrentHashMap<String, Cluster> clustersByName = null;
+ private ConcurrentHashMap<Long, Cluster> clustersById = null;
+ private ConcurrentHashMap<String, Host> hostsByName = null;
+ private ConcurrentHashMap<Long, Host> hostsById = null;
+ private ConcurrentHashMap<String, Set<Cluster>> hostClustersMap = null;
+ private ConcurrentHashMap<String, Set<Host>> clusterHostsMap1 = null;
@Inject
private ClusterDAO clusterDAO;
@@ -169,41 +169,142 @@ public class ClustersImpl implements Clusters {
}
/**
- * Inititalizes all of the in-memory state collections that this class
- * unfortunately uses. It's annotated with {@link Inject} as a way to define
a
- * very simple lifecycle with Guice where the constructor is instantiated
- * (allowing injected members) followed by this method which initiailizes the
- * state of the instance.
+ * Gets the internal clusters-by-name map, ensuring that the relevant data
has been previously initialized.
+ *
+ * @return a map of the requested data
+ */
+ private ConcurrentHashMap<String, Cluster> getClustersByName() {
+ if (clustersByName == null) {
+ safelyLoadClustersAndHosts();
+ }
+ return clustersByName;
+ }
+
+ /**
+ * Gets the internal clusters-by-id map, ensuring that the relevant data has
been previously initialized.
+ *
+ * @return a map of the requested data
+ */
+ private ConcurrentHashMap<Long, Cluster> getClustersById() {
+ if (clustersById == null) {
+ safelyLoadClustersAndHosts();
+ }
+ return clustersById;
+ }
+
+ /**
+ * Gets the internal hosts-by-name map, ensuring that the relevant data has
been previously initialized.
+ *
+ * @return a map of the requested data
+ */
+ private ConcurrentHashMap<String, Host> getHostsByName() {
+ if (hostsByName == null) {
+ safelyLoadClustersAndHosts();
+ }
+ return hostsByName;
+ }
+
+ /**
+ * Gets the internal hosts-by-id map, ensuring that the relevant data has
been previously initialized.
+ *
+ * @return a map of the requested data
+ */
+ private ConcurrentHashMap<Long, Host> getHostsById() {
+ if (hostsById == null) {
+ safelyLoadClustersAndHosts();
+ }
+ return hostsById;
+ }
+
+ /**
+ * Gets the internal host/clusters map, ensuring that the relevant data has
been previously initialized.
+ *
+ * @return a map of the requested data
+ */
+ private ConcurrentHashMap<String, Set<Cluster>> getHostClustersMap() {
+ if (hostClustersMap == null) {
+ safelyLoadClustersAndHosts();
+ }
+ return hostClustersMap;
+ }
+
+ /**
+ * Gets the internal cluster/hosts map, ensuring that the relevant data has
been previously initialized.
+ *
+ * @return a map of the requested data
+ */
+ private ConcurrentHashMap<String, Set<Host>> getClusterHostsMap() {
+ if (clusterHostsMap1 == null) {
+ safelyLoadClustersAndHosts();
+ }
+ return clusterHostsMap1;
+ }
+
+ /**
+ * Safely initializes all of the in-memory state collections that this class.
+ * <p>
+ * This method is synchronized so that the data can be loaded only if
needed. If most than one of
+ * the relevant get methods are concurrently invoked, this method should
ensure that {@link #loadClustersAndHosts()}
+ * will be entered once. Subsequent calls will bypass {@link
#loadClustersAndHosts()} since the
+ * relevant variables will no longer be null.
+ *
+ * @see #getClustersByName()
+ * @see #getClustersById()
+ * @see #getHostsByName()
+ * @see #getHostsById()
+ * @see #getClusterHostsMap()
+ * @see #getHostClustersMap()
+ */
+ synchronized private void safelyLoadClustersAndHosts() {
+ if (clustersByName == null || clustersById == null ||
+ hostsByName == null || hostsById == null ||
+ hostClustersMap == null || clusterHostsMap1 == null) {
+ loadClustersAndHosts();
+ }
+ }
+
+ /**
+ * Initializes all of the in-memory state collections that this class
+ * unfortunately uses.
+ * <p>
+ * This method should be called only once, when the data is first needed.
* <p/>
* Because some of these stateful initializations may actually reference this
* {@link Clusters} instance, we must do this after the object has been
* instantiated and injected.
*/
- @Inject
- @Transactional
- void loadClustersAndHosts() {
+ private void loadClustersAndHosts() {
+ LOG.info("Initializing cluster and host data.");
+
+ clustersByName = new ConcurrentHashMap<>();
+ clustersById = new ConcurrentHashMap<>();
+ hostsByName = new ConcurrentHashMap<>();
+ hostsById = new ConcurrentHashMap<>();
+ hostClustersMap = new ConcurrentHashMap<>();
+ clusterHostsMap1 = new ConcurrentHashMap<>();
+
List<HostEntity> hostEntities = hostDAO.findAll();
for (HostEntity hostEntity : hostEntities) {
Host host = hostFactory.create(hostEntity);
- hosts.put(hostEntity.getHostName(), host);
+ hostsByName.put(hostEntity.getHostName(), host);
hostsById.put(hostEntity.getHostId(), host);
}
for (ClusterEntity clusterEntity : clusterDAO.findAll()) {
Cluster currentCluster = clusterFactory.create(clusterEntity);
- clusters.put(clusterEntity.getClusterName(), currentCluster);
+ clustersByName.put(clusterEntity.getClusterName(), currentCluster);
clustersById.put(currentCluster.getClusterId(), currentCluster);
- clusterHostMap.put(currentCluster.getClusterName(),
Collections.newSetFromMap(new ConcurrentHashMap<>()));
+ clusterHostsMap1.put(currentCluster.getClusterName(),
Collections.newSetFromMap(new ConcurrentHashMap<>()));
}
for (HostEntity hostEntity : hostEntities) {
Set<Cluster> cSet = Collections.newSetFromMap(new
ConcurrentHashMap<Cluster, Boolean>());
- hostClusterMap.put(hostEntity.getHostName(), cSet);
+ hostClustersMap.put(hostEntity.getHostName(), cSet);
- Host host = hosts.get(hostEntity.getHostName());
+ Host host = getHostsByName().get(hostEntity.getHostName());
for (ClusterEntity clusterEntity : hostEntity.getClusterEntities()) {
- clusterHostMap.get(clusterEntity.getClusterName()).add(host);
- cSet.add(clusters.get(clusterEntity.getClusterName()));
+ clusterHostsMap1.get(clusterEntity.getClusterName()).add(host);
+ cSet.add(clustersByName.get(clusterEntity.getClusterName()));
}
}
}
@@ -219,7 +320,7 @@ public class ClustersImpl implements Clusters {
throws AmbariException {
Cluster cluster = null;
- if (clusters.containsKey(clusterName)) {
+ if (getClustersByName().containsKey(clusterName)) {
throw new DuplicateResourceException(
"Attempted to create a Cluster which already exists" + ",
clusterName=" + clusterName);
}
@@ -256,9 +357,9 @@ public class ClustersImpl implements Clusters {
}
cluster = clusterFactory.create(clusterEntity);
- clusters.put(clusterName, cluster);
- clustersById.put(cluster.getClusterId(), cluster);
- clusterHostMap.put(clusterName,
+ getClustersByName().put(clusterName, cluster);
+ getClustersById().put(cluster.getClusterId(), cluster);
+ getClusterHostsMap().put(clusterName,
Collections.newSetFromMap(new ConcurrentHashMap<>()));
cluster.setCurrentStackVersion(stackId);
@@ -277,7 +378,7 @@ public class ClustersImpl implements Clusters {
throws AmbariException {
Cluster cluster = null;
if (clusterName != null) {
- cluster = clusters.get(clusterName);
+ cluster = getClustersByName().get(clusterName);
}
if (null == cluster) {
throw new ClusterNotFoundException(clusterName);
@@ -291,7 +392,7 @@ public class ClustersImpl implements Clusters {
throws AmbariException {
Cluster cluster = null;
if (clusterId != null) {
- cluster = clustersById.get(clusterId);
+ cluster = getClustersById().get(clusterId);
}
if (null == cluster) {
throw new ClusterNotFoundException(clusterId);
@@ -302,6 +403,7 @@ public class ClustersImpl implements Clusters {
@Override
public Cluster getClusterById(long id) throws AmbariException {
+ ConcurrentHashMap<Long, Cluster> clustersById = getClustersById();
Cluster cluster = clustersById.get(id);
if (null == cluster) {
throw new ClusterNotFoundException("clusterID=" + id);
@@ -312,13 +414,13 @@ public class ClustersImpl implements Clusters {
@Override
public List<Host> getHosts() {
- return new ArrayList<>(hosts.values());
+ return new ArrayList<>(getHostsByName().values());
}
@Override
public Set<Cluster> getClustersForHost(String hostname)
throws AmbariException {
- Set<Cluster> clusters = hostClusterMap.get(hostname);
+ Set<Cluster> clusters = getHostClustersMap().get(hostname);
if(clusters == null){
throw new HostNotFoundException(hostname);
}
@@ -331,7 +433,7 @@ public class ClustersImpl implements Clusters {
@Override
public Host getHost(String hostname) throws AmbariException {
- Host host = hosts.get(hostname);
+ Host host = getHostsByName().get(hostname);
if (null == host) {
throw new HostNotFoundException(hostname);
}
@@ -341,7 +443,7 @@ public class ClustersImpl implements Clusters {
@Override
public boolean hostExists(String hostname){
- return hosts.containsKey(hostname);
+ return getHostsByName().containsKey(hostname);
}
/**
@@ -349,7 +451,7 @@ public class ClustersImpl implements Clusters {
*/
@Override
public boolean isHostMappedToCluster(long clusterId, String hostName) {
- Set<Cluster> clusters = hostClusterMap.get(hostName);
+ Set<Cluster> clusters = getHostClustersMap().get(hostName);
for (Cluster cluster : clusters) {
if (clusterId == cluster.getClusterId()) {
return true;
@@ -361,11 +463,11 @@ public class ClustersImpl implements Clusters {
@Override
public Host getHostById(Long hostId) throws AmbariException {
- if (!hostsById.containsKey(hostId)) {
+ if (!getHostsById().containsKey(hostId)) {
throw new HostNotFoundException("Host Id = " + hostId);
}
- return hostsById.get(hostId);
+ return getHostsById().get(hostId);
}
/**
@@ -376,7 +478,7 @@ public class ClustersImpl implements Clusters {
Long hostId = host.getHostId();
if (null != hostId) {
- hostsById.put(hostId, host);
+ getHostsById().put(hostId, host);
}
}
@@ -388,7 +490,7 @@ public class ClustersImpl implements Clusters {
*/
@Override
public void addHost(String hostname) throws AmbariException {
- if (hosts.containsKey(hostname)) {
+ if (getHostsByName().containsKey(hostname)) {
throw new AmbariException(MessageFormat.format("Duplicate entry for Host
{0}", hostname));
}
@@ -407,9 +509,9 @@ public class ClustersImpl implements Clusters {
// the hosts by ID map is updated separately since the host has not yet
// been persisted yet - the below event is what causes the persist
- hosts.put(hostname, host);
+ getHostsByName().put(hostname, host);
- hostClusterMap.put(hostname,
+ getHostClustersMap().put(hostname,
Collections.newSetFromMap(new ConcurrentHashMap<>()));
if (LOG.isDebugEnabled()) {
@@ -469,7 +571,7 @@ public class ClustersImpl implements Clusters {
Host host = null;
for (String hostName : hostSet) {
if (null != hostName) {
- host= hosts.get(hostName);
+ host= getHostsByName().get(hostName);
if (host == null) {
throw new HostNotFoundException(hostName);
}
@@ -516,9 +618,10 @@ public class ClustersImpl implements Clusters {
Host host = getHost(hostname);
Cluster cluster = getCluster(clusterName);
+ ConcurrentHashMap<String, Set<Cluster>> hostClustersMap =
getHostClustersMap();
// check to ensure there are no duplicates
- for (Cluster c : hostClusterMap.get(hostname)) {
+ for (Cluster c : hostClustersMap.get(hostname)) {
if (c.getClusterName().equals(clusterName)) {
throw new DuplicateResourceException("Attempted to create a host which
already exists: clusterName=" +
clusterName + ", hostName=" + hostname);
@@ -532,8 +635,8 @@ public class ClustersImpl implements Clusters {
}
mapHostClusterEntities(hostname, clusterId);
- hostClusterMap.get(hostname).add(cluster);
- clusterHostMap.get(clusterName).add(host);
+ hostClustersMap.get(hostname).add(cluster);
+ getClusterHostsMap().get(clusterName).add(host);
}
@Transactional
@@ -550,13 +653,16 @@ public class ClustersImpl implements Clusters {
@Override
public Map<String, Cluster> getClusters() {
- return Collections.unmodifiableMap(clusters);
+ return Collections.unmodifiableMap(getClustersByName());
}
@Override
public void updateClusterName(String oldName, String newName) {
+ ConcurrentHashMap<String, Cluster> clusters = getClustersByName();
clusters.put(newName, clusters.remove(oldName));
- clusterHostMap.put(newName, clusterHostMap.remove(oldName));
+
+ ConcurrentHashMap<String, Set<Host>> clusterHostsMap =
getClusterHostsMap();
+ clusterHostsMap.put(newName, clusterHostsMap.remove(oldName));
//TODO metadata update
}
@@ -566,7 +672,7 @@ public class ClustersImpl implements Clusters {
public void debugDump(StringBuilder sb) {
sb.append("Clusters=[ ");
boolean first = true;
- for (Cluster c : clusters.values()) {
+ for (Cluster c : getClustersByName().values()) {
if (!first) {
sb.append(" , ");
}
@@ -583,7 +689,7 @@ public class ClustersImpl implements Clusters {
throws AmbariException {
Map<String, Host> hosts = new HashMap<>();
- for (Host h : clusterHostMap.get(clusterName)) {
+ for (Host h : getClusterHostsMap().get(clusterName)) {
hosts.put(h.getHostName(), h);
}
@@ -595,7 +701,7 @@ public class ClustersImpl implements Clusters {
throws AmbariException {
Map<Long, Host> hosts = new HashMap<>();
- for (Host h : clusterHostMap.get(clusterName)) {
+ for (Host h : getClusterHostsMap().get(clusterName)) {
HostEntity hostEntity = hostDAO.findByName(h.getHostName());
hosts.put(hostEntity.getHostId(), h);
}
@@ -615,11 +721,11 @@ public class ClustersImpl implements Clusters {
cluster.delete();
// clear maps
- for (Set<Cluster> clusterSet : hostClusterMap.values()) {
+ for (Set<Cluster> clusterSet : getHostClustersMap().values()) {
clusterSet.remove(cluster);
}
- clusterHostMap.remove(cluster.getClusterName());
- clusters.remove(clusterName);
+ getClusterHostsMap().remove(cluster.getClusterName());
+ getClustersByName().remove(clusterName);
}
@Override
@@ -652,8 +758,8 @@ public class ClustersImpl implements Clusters {
unmapHostClusterEntities(hostname, cluster.getClusterId());
- hostClusterMap.get(hostname).remove(cluster);
- clusterHostMap.get(cluster.getClusterName()).remove(host);
+ getHostClustersMap().get(hostname).remove(cluster);
+ getClusterHostsMap().get(cluster.getClusterName()).remove(host);
}
deleteConfigGroupHostMapping(hostEntity.getHostId());
@@ -677,7 +783,7 @@ public class ClustersImpl implements Clusters {
@Transactional
void deleteConfigGroupHostMapping(Long hostId) throws AmbariException {
// Remove Config group mapping
- for (Cluster cluster : clusters.values()) {
+ for (Cluster cluster : getClustersByName().values()) {
for (ConfigGroup configGroup : cluster.getConfigGroups().values()) {
configGroup.removeHost(hostId);
}
@@ -697,7 +803,7 @@ public class ClustersImpl implements Clusters {
// unmapping hosts from a cluster modifies the collections directly; keep
// a copy of this to ensure that we can pass in the original set of
// clusters that the host belonged to to the host removal event
- Set<Cluster> clusters = hostClusterMap.get(hostname);
+ Set<Cluster> clusters = getHostClustersMap().get(hostname);
if (clusters == null) {
throw new HostNotFoundException(hostname);
}
@@ -724,7 +830,7 @@ public class ClustersImpl implements Clusters {
*/
@Transactional
void deleteHostEntityRelationships(String hostname) throws AmbariException {
- if (!hosts.containsKey(hostname)) {
+ if (!getHostsByName().containsKey(hostname)) {
throw new HostNotFoundException("Could not find host " + hostname);
}
@@ -737,13 +843,13 @@ public class ClustersImpl implements Clusters {
// Remove from all clusters in the cluster_host_mapping table.
// This will also remove from kerberos_principal_hosts, hostconfigmapping,
// and configgrouphostmapping
- Set<Cluster> clusters = hostClusterMap.get(hostname);
+ Set<Cluster> clusters = getHostClustersMap().get(hostname);
Set<Long> clusterIds = Sets.newHashSet();
for (Cluster cluster : clusters) {
clusterIds.add(cluster.getClusterId());
}
- Host host = hosts.get(hostname);
+ Host host = getHostsByName().get(hostname);
unmapHostFromClusters(host, clusters);
hostDAO.refresh(entity);
@@ -772,8 +878,8 @@ public class ClustersImpl implements Clusters {
topologyHostInfoDAO.removeByHost(entity);
// Remove from dictionaries
- hosts.remove(hostname);
- hostsById.remove(entity.getHostId());
+ getHostsByName().remove(hostname);
+ getHostsById().remove(entity.getHostId());
hostDAO.remove(entity);
@@ -812,10 +918,10 @@ public class ClustersImpl implements Clusters {
@Override
public int getClusterSize(String clusterName) {
int hostCount = 0;
-
- Set<Host> hosts = clusterHostMap.get(clusterName);
+ ConcurrentHashMap<String, Set<Host>> clusterHostsMap =
getClusterHostsMap();
+ Set<Host> hosts = clusterHostsMap.get(clusterName);
if (null != hosts) {
- hostCount = clusterHostMap.get(clusterName).size();
+ hostCount = clusterHostsMap.get(clusterName).size();
}
return hostCount;
@@ -879,7 +985,7 @@ public class ClustersImpl implements Clusters {
public void invalidate(Cluster cluster) {
ClusterEntity clusterEntity = clusterDAO.findById(cluster.getClusterId());
Cluster currentCluster = clusterFactory.create(clusterEntity);
- clusters.put(clusterEntity.getClusterName(), currentCluster);
- clustersById.put(currentCluster.getClusterId(), currentCluster);
+ getClustersByName().put(clusterEntity.getClusterName(), currentCluster);
+ getClustersById().put(currentCluster.getClusterId(), currentCluster);
}
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
index cbba599..de80052 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
@@ -38,6 +38,7 @@ import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.ControllerModule;
import org.apache.ambari.server.ldap.LdapModule;
import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.utils.EventBusSynchronizer;
import org.apache.ambari.server.utils.VersionUtils;
import org.slf4j.Logger;
@@ -403,6 +404,11 @@ public class SchemaUpgradeHelper {
}
Injector injector = Guice.createInjector(new UpgradeHelperModule(), new
AuditLoggerModule(), new LdapModule());
+
+ // Startup the JPA infrastructure, but do not indicate it is initialized
since the underlying
+ // database schema may not be updated to meet the expectations of the
Entity instances.
+ GuiceJpaInitializer jpaInitializer =
injector.getInstance(GuiceJpaInitializer.class);
+
SchemaUpgradeHelper schemaUpgradeHelper =
injector.getInstance(SchemaUpgradeHelper.class);
//Fail if MySQL database has tables with MyISAM engine
@@ -441,7 +447,9 @@ public class SchemaUpgradeHelper {
schemaUpgradeHelper.executeUpgrade(upgradeCatalogs);
- schemaUpgradeHelper.startPersistenceService();
+ // The DDL is expected to be updated, now send the JPA initialized event
so Entity
+ // implementations can be created.
+ jpaInitializer.setInitialized();
schemaUpgradeHelper.executePreDMLUpdates(upgradeCatalogs);
@@ -457,6 +465,9 @@ public class SchemaUpgradeHelper {
schemaUpgradeHelper.cleanUpRCATables();
schemaUpgradeHelper.stopPersistenceService();
+
+ // Signal all threads that we are ready to exit...
+ System.exit(0);
} catch (Throwable e) {
if (e instanceof AmbariException) {
LOG.error("Exception occurred during upgrade, failed", e);
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
index 02474e8..d59248d 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog270.java
@@ -83,6 +83,11 @@ import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import com.google.common.net.HostAndPort;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
import com.google.inject.Inject;
import com.google.inject.Injector;
@@ -107,6 +112,10 @@ public class UpgradeCatalog270 extends
AbstractUpgradeCatalog {
protected static final String SERVICE_DESIRED_STATE_TABLE =
"servicedesiredstate";
protected static final String SECURITY_STATE_COLUMN = "security_state";
+ protected static final String AMBARI_SEQUENCES_TABLE = "ambari_sequences";
+ protected static final String AMBARI_SEQUENCES_SEQUENCE_NAME_COLUMN =
"sequence_name";
+ protected static final String AMBARI_SEQUENCES_SEQUENCE_VALUE_COLUMN =
"sequence_value";
+
protected static final String AMBARI_CONFIGURATION_TABLE =
"ambari_configuration";
protected static final String AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN =
"category_name";
protected static final String AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN =
"property_name";
@@ -178,6 +187,36 @@ public class UpgradeCatalog270 extends
AbstractUpgradeCatalog {
protected static final String KERBEROS_PRINCIPAL_HOST_TABLE =
"kerberos_principal_host";
protected static final String HOST_ID_COLUMN = "host_id";
+ protected static final String REPO_OS_TABLE = "repo_os";
+ protected static final String REPO_OS_ID_COLUMN = "id";
+ protected static final String REPO_OS_REPO_VERSION_ID_COLUMN =
"repo_version_id";
+ protected static final String REPO_OS_FAMILY_COLUMN = "family";
+ protected static final String REPO_OS_AMBARI_MANAGED_COLUMN =
"ambari_managed";
+ protected static final String REPO_OS_PRIMARY_KEY = "PK_repo_os_id";
+ protected static final String REPO_OS_FOREIGN_KEY =
"FK_repo_os_id_repo_version_id";
+
+ protected static final String REPO_DEFINITION_TABLE = "repo_definition";
+ protected static final String REPO_DEFINITION_ID_COLUMN = "id";
+ protected static final String REPO_DEFINITION_REPO_OS_ID_COLUMN =
"repo_os_id";
+ protected static final String REPO_DEFINITION_REPO_NAME_COLUMN = "repo_name";
+ protected static final String REPO_DEFINITION_REPO_ID_COLUMN = "repo_id";
+ protected static final String REPO_DEFINITION_BASE_URL_COLUMN = "base_url";
+ protected static final String REPO_DEFINITION_DISTRIBUTION_COLUMN =
"distribution";
+ protected static final String REPO_DEFINITION_COMPONENTS_COLUMN =
"components";
+ protected static final String REPO_DEFINITION_UNIQUE_REPO_COLUMN =
"unique_repo";
+ protected static final String REPO_DEFINITION_MIRRORS_COLUMN = "mirrors";
+ protected static final String REPO_DEFINITION_PRIMARY_KEY =
"PK_repo_definition_id";
+ protected static final String REPO_DEFINITION_FOREIGN_KEY =
"FK_repo_definition_repo_os_id";
+
+ protected static final String REPO_TAGS_TABLE = "repo_tags";
+ protected static final String REPO_TAGS_REPO_DEFINITION_ID_COLUMN =
"repo_definition_id";
+ protected static final String REPO_TAGS_TAG_COLUMN = "tag";
+ protected static final String REPO_TAGS_FOREIGN_KEY =
"FK_repo_tag_definition_id";
+
+ protected static final String REPO_VERSION_TABLE = "repo_version";
+ protected static final String REPO_VERSION_REPO_VERSION_ID_COLUMN =
"repo_version_id";
+ protected static final String REPO_VERSION_REPOSITORIES_COLUMN =
"repositories";
+
protected static final String CLUSTER_ID_COLUMN = "cluster_id";
public static final String[]
COMPONENT_NAME_SERVICE_NAME_CLUSTER_ID_KEY_COLUMNS = {COMPONENT_NAME_COLUMN,
SERVICE_NAME_COLUMN, CLUSTER_ID_COLUMN};
public static final String[] SERVICE_NAME_CLUSTER_ID_KEY_COLUMNS =
{SERVICE_NAME_COLUMN, CLUSTER_ID_COLUMN};
@@ -240,6 +279,7 @@ public class UpgradeCatalog270 extends
AbstractUpgradeCatalog {
addHostComponentLastStateTable();
upgradeUserTables();
upgradeKerberosTables();
+ upgradeRepoTables();
}
/**
@@ -266,6 +306,200 @@ public class UpgradeCatalog270 extends
AbstractUpgradeCatalog {
updateUsersTable();
}
+ protected void upgradeRepoTables() throws SQLException {
+ createRepoOsTable();
+ createRepoDefinitionTable();
+ createRepoTagsTable();
+ migrateRepoData();
+ updateRepoVersionTable();
+ }
+
+ /**
+ * Adds the repo_os table to the Ambari database.
+ * <pre>
+ * CREATE TABLE repo_os (
+ * id BIGINT NOT NULL,
+ * repo_version_id BIGINT NOT NULL,
+ * family VARCHAR(255) NOT NULL DEFAULT '',
+ * ambari_managed SMALLINT DEFAULT 1,
+ * CONSTRAINT PK_repo_os_id PRIMARY KEY (id),
+ * CONSTRAINT FK_repo_os_id_repo_version_id FOREIGN KEY (repo_version_id)
REFERENCES repo_version (repo_version_id));
+ * </pre>
+ *
+ * @throws SQLException
+ */
+ private void createRepoOsTable() throws SQLException {
+ List<DBAccessor.DBColumnInfo> columns = new ArrayList<>();
+ columns.add(new DBAccessor.DBColumnInfo(REPO_OS_ID_COLUMN, Long.class,
null, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_OS_REPO_VERSION_ID_COLUMN,
Long.class, null, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_OS_FAMILY_COLUMN,
String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_OS_AMBARI_MANAGED_COLUMN,
Integer.class, null, 1, true));
+
+ dbAccessor.createTable(REPO_OS_TABLE, columns);
+ dbAccessor.addPKConstraint(REPO_OS_TABLE, REPO_OS_PRIMARY_KEY,
REPO_OS_ID_COLUMN);
+ dbAccessor.addFKConstraint(REPO_OS_TABLE, REPO_OS_FOREIGN_KEY,
REPO_OS_REPO_VERSION_ID_COLUMN, REPO_VERSION_TABLE,
REPO_VERSION_REPO_VERSION_ID_COLUMN, false);
+ }
+
+ /**
+ * Adds the repo_definition table to the Ambari database.
+ * <pre>
+ * CREATE TABLE repo_definition (
+ * id BIGINT NOT NULL,
+ * repo_os_id BIGINT,
+ * repo_name VARCHAR(255) NOT NULL,
+ * repo_id VARCHAR(255) NOT NULL,
+ * base_url VARCHAR(2048) NOT NULL,
+ * distribution VARCHAR(2048),
+ * components VARCHAR(2048),
+ * unique_repo SMALLINT DEFAULT 1,
+ * mirrors VARCHAR(2048),
+ * CONSTRAINT PK_repo_definition_id PRIMARY KEY (id),
+ * CONSTRAINT FK_repo_definition_repo_os_id FOREIGN KEY (repo_os_id)
REFERENCES repo_os (id));
+ * </pre>
+ *
+ * @throws SQLException
+ */
+ private void createRepoDefinitionTable() throws SQLException {
+ List<DBAccessor.DBColumnInfo> columns = new ArrayList<>();
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_ID_COLUMN,
Long.class, null, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_REPO_OS_ID_COLUMN,
Long.class, null, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_REPO_NAME_COLUMN,
String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_REPO_ID_COLUMN,
String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_BASE_URL_COLUMN,
String.class, 2048, null, true));
+ columns.add(new
DBAccessor.DBColumnInfo(REPO_DEFINITION_DISTRIBUTION_COLUMN, String.class,
2048, null, true));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_COMPONENTS_COLUMN,
String.class, 2048, null, true));
+ columns.add(new
DBAccessor.DBColumnInfo(REPO_DEFINITION_UNIQUE_REPO_COLUMN, Integer.class, 1,
1, true));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_DEFINITION_MIRRORS_COLUMN,
String.class, 2048, null, true));
+
+ dbAccessor.createTable(REPO_DEFINITION_TABLE, columns);
+ dbAccessor.addPKConstraint(REPO_DEFINITION_TABLE,
REPO_DEFINITION_PRIMARY_KEY, REPO_DEFINITION_ID_COLUMN);
+ dbAccessor.addFKConstraint(REPO_DEFINITION_TABLE,
REPO_DEFINITION_FOREIGN_KEY, REPO_DEFINITION_REPO_OS_ID_COLUMN, REPO_OS_TABLE,
REPO_OS_ID_COLUMN, false);
+ }
+
+ /**
+ * Adds the repo_tags table to the Ambari database.
+ * <pre>
+ * CREATE TABLE repo_tags (
+ * repo_definition_id BIGINT NOT NULL,
+ * tag VARCHAR(255) NOT NULL,
+ * CONSTRAINT FK_repo_tag_definition_id FOREIGN KEY (repo_definition_id)
REFERENCES repo_definition (id));
+ * </pre>
+ *
+ * @throws SQLException
+ */
+ private void createRepoTagsTable() throws SQLException {
+ List<DBAccessor.DBColumnInfo> columns = new ArrayList<>();
+ columns.add(new
DBAccessor.DBColumnInfo(REPO_TAGS_REPO_DEFINITION_ID_COLUMN, Long.class, null,
null, false));
+ columns.add(new DBAccessor.DBColumnInfo(REPO_TAGS_TAG_COLUMN,
String.class, 255, null, false));
+
+ dbAccessor.createTable(REPO_TAGS_TABLE, columns);
+ dbAccessor.addFKConstraint(REPO_TAGS_TABLE, REPO_TAGS_FOREIGN_KEY,
REPO_TAGS_REPO_DEFINITION_ID_COLUMN, REPO_DEFINITION_TABLE,
REPO_DEFINITION_ID_COLUMN, false);
+ }
+
+ /**
+ * Perform steps to move data from the old repo_version.repositories
structure into new tables -
+ * repo_os, repo_definition, repo_tags
+ *
+ * @throws SQLException
+ */
+ private void migrateRepoData() throws SQLException {
+ if(dbAccessor.tableHasColumn(REPO_VERSION_TABLE,
REPO_VERSION_REPOSITORIES_COLUMN)) {
+ int repoOsId = 0;
+ int repoDefinitionId = 0;
+
+ // Get a map of repo_version.id to repo_version.repositories
+ Map<Long, String> repoVersionData =
dbAccessor.getKeyToStringColumnMap(REPO_VERSION_TABLE,
+ REPO_VERSION_REPO_VERSION_ID_COLUMN,
REPO_VERSION_REPOSITORIES_COLUMN, null, null, true);
+
+ if (repoVersionData != null) {
+ // For each entry in the map, parse the repo_version.repositories data
and created records in the new
+ // repo_os, repo_definition, and repo_tabs tables...
+ for (Map.Entry<Long, String> entry : repoVersionData.entrySet()) {
+ Long repoVersionId = entry.getKey();
+ String repositoriesJson = entry.getValue();
+
+ if (!StringUtils.isEmpty(repositoriesJson)) {
+ JsonArray rootJson = new
JsonParser().parse(repositoriesJson).getAsJsonArray();
+
+ if (rootJson != null) {
+ for (JsonElement rootElement : rootJson) {
+ // process each OS element
+ JsonObject rootObject = rootElement.getAsJsonObject();
+
+ if (rootObject != null) {
+ JsonPrimitive osType =
rootObject.getAsJsonPrimitive("OperatingSystems/os_type");
+ JsonPrimitive ambariManaged =
rootObject.getAsJsonPrimitive("OperatingSystems/ambari_managed_repositories");
+ JsonArray repositories =
rootObject.getAsJsonArray("repositories");
+ String isAmbariManaged = ambariManaged.getAsBoolean() ? "1"
: "0";
+
+ dbAccessor.insertRowIfMissing(REPO_OS_TABLE,
+ new String[]{REPO_OS_ID_COLUMN,
REPO_OS_REPO_VERSION_ID_COLUMN, REPO_OS_AMBARI_MANAGED_COLUMN,
REPO_OS_FAMILY_COLUMN},
+ new String[]{String.valueOf(++repoOsId),
String.valueOf(repoVersionId), isAmbariManaged, String.format("'%s'",
osType.getAsString())},
+ false);
+
+ if (repositories != null) {
+ for (JsonElement repositoryElement : repositories) {
+ JsonObject repositoryObject =
repositoryElement.getAsJsonObject();
+
+ if (repositoryObject != null) {
+ JsonPrimitive repoId =
repositoryObject.getAsJsonPrimitive("Repositories/repo_id");
+ JsonPrimitive repoName =
repositoryObject.getAsJsonPrimitive("Repositories/repo_name");
+ JsonPrimitive baseUrl =
repositoryObject.getAsJsonPrimitive("Repositories/base_url");
+ JsonArray tags =
repositoryObject.getAsJsonArray("Repositories/tags");
+
+ dbAccessor.insertRowIfMissing(REPO_DEFINITION_TABLE,
+ new String[]{REPO_DEFINITION_ID_COLUMN,
REPO_DEFINITION_REPO_OS_ID_COLUMN,
+ REPO_DEFINITION_REPO_NAME_COLUMN,
REPO_DEFINITION_REPO_ID_COLUMN, REPO_DEFINITION_BASE_URL_COLUMN},
+ new String[]{String.valueOf(++repoDefinitionId),
String.valueOf(repoOsId),
+ String.format("'%s'", repoName.getAsString()),
String.format("'%s'", repoId.getAsString()),
+ String.format("'%s'", baseUrl.getAsString())},
+ false);
+
+ if (tags != null) {
+ for (JsonElement tagsElement : tags) {
+ JsonPrimitive tag =
tagsElement.getAsJsonPrimitive();
+
+ if (tag != null) {
+ dbAccessor.insertRowIfMissing(REPO_TAGS_TABLE,
+ new
String[]{REPO_TAGS_REPO_DEFINITION_ID_COLUMN, REPO_TAGS_TAG_COLUMN},
+ new
String[]{String.valueOf(repoDefinitionId), String.format("'%s'",
tag.getAsString())},
+ false);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Add the relevant records in the ambari_sequence table
+ // - repo_os_id_seq
+ // - repo_definition_id_seq
+ dbAccessor.insertRowIfMissing(AMBARI_SEQUENCES_TABLE,
+ new String[]{AMBARI_SEQUENCES_SEQUENCE_NAME_COLUMN,
AMBARI_SEQUENCES_SEQUENCE_VALUE_COLUMN},
+ new String[]{"'repo_os_id_seq'", String.valueOf(++repoOsId)},
+ false);
+ dbAccessor.insertRowIfMissing(AMBARI_SEQUENCES_TABLE,
+ new String[]{AMBARI_SEQUENCES_SEQUENCE_NAME_COLUMN,
AMBARI_SEQUENCES_SEQUENCE_VALUE_COLUMN},
+ new String[]{"'repo_definition_id_seq'",
String.valueOf(++repoDefinitionId)},
+ false);
+ }
+ }
+
+ /**
+ * Updates the repo_version table by removing old columns
+ *
+ * @throws SQLException
+ */
+ private void updateRepoVersionTable() throws SQLException {
+ dbAccessor.dropColumn(REPO_VERSION_TABLE,
REPO_VERSION_REPOSITORIES_COLUMN);
+ }
+
/**
* If the <code>users</code> table has not yet been migrated, create the
<code>user_authentication</code>
* table and generate relevant records for that table based on data in the
<code>users</code> table.
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/orm/DBAccessorImplTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/orm/DBAccessorImplTest.java
index 68b0cdf..15c83bb 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/orm/DBAccessorImplTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/orm/DBAccessorImplTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.junit.matchers.JUnitMatchers.containsString;
import java.io.ByteArrayInputStream;
@@ -785,4 +786,73 @@ public class DBAccessorImplTest {
assertFalse(column1.equals(notEqualsColumn1DefaultValueEmptyString));
assertFalse(column1.equals(notEqualsColumn1Nullable));
}
+
+ @Test
+ public void testBuildQuery() throws Exception {
+ String tableName = getFreeTableName();
+ createMyTable(tableName);
+
+ DBAccessorImpl dbAccessor = injector.getInstance(DBAccessorImpl.class);
+
+ assertEquals(String.format("SELECT id FROM %s WHERE name='value1'",
tableName),
+ dbAccessor.buildQuery(tableName, new String[] {"id"}, new String[]
{"name"}, new String[] {"value1"}));
+
+ assertEquals(String.format("SELECT id FROM %s WHERE name='value1' AND
time='100'", tableName),
+ dbAccessor.buildQuery(tableName, new String[] {"id"}, new String[]
{"name", "time"}, new String[] {"value1", "100"}));
+
+ assertEquals(String.format("SELECT id, name FROM %s WHERE time='100'",
tableName),
+ dbAccessor.buildQuery(tableName, new String[] {"id", "name"}, new String[]
{"time"}, new String[] {"100"}));
+
+ assertEquals(String.format("SELECT id, name FROM %s", tableName),
+ dbAccessor.buildQuery(tableName, new String[] {"id", "name"}, null, null));
+
+ try {
+ dbAccessor.buildQuery("invalid_table_name", new String[] {"id", "name"},
new String[] {"time"}, new String[] {"100"});
+ fail("Expected IllegalArgumentException due to bad table name");
+ }
+ catch (IllegalArgumentException e) {
+ // This is expected
+ }
+
+ try {
+ dbAccessor.buildQuery(tableName, new String[] {"invalid_column_name"},
new String[] {"time"}, new String[] {"100"});
+ fail("Expected IllegalArgumentException due to bad column name");
+ }
+ catch (IllegalArgumentException e) {
+ // This is expected
+ }
+
+ try {
+ dbAccessor.buildQuery(tableName, new String[] {"id"}, new String[]
{"invalid_column_name"}, new String[] {"100"});
+ fail("Expected IllegalArgumentException due to bad column name");
+ }
+ catch (IllegalArgumentException e) {
+ // This is expected
+ }
+
+ try {
+ dbAccessor.buildQuery(tableName, new String[] {}, new String[] {"name"},
new String[] {"100"});
+ fail("Expected IllegalArgumentException due missing select columns");
+ }
+ catch (IllegalArgumentException e) {
+ // This is expected
+ }
+
+ try {
+ dbAccessor.buildQuery(tableName, null, new String[] {"name"}, new
String[] {"100"});
+ fail("Expected IllegalArgumentException due missing select columns");
+ }
+ catch (IllegalArgumentException e) {
+ // This is expected
+ }
+
+ try {
+ dbAccessor.buildQuery(tableName, new String[] {"id"}, new String[]
{"name", "time"}, new String[] {"100"});
+ fail("Expected IllegalArgumentException due mismatch condition column
and value arrays");
+ }
+ catch (IllegalArgumentException e) {
+ // This is expected
+ }
+ }
+
}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
index 5f6e24a..7d502be 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/security/ldap/AmbariLdapDataPopulatorTest.java
@@ -236,7 +236,6 @@ public class AmbariLdapDataPopulatorTest {
LdapServerProperties ldapServerProperties =
createNiceMock(LdapServerProperties.class);
expect(configurationProvider.get()).andReturn(configuration).anyTimes();
expect(configuration.ldapEnabled()).andReturn(false);
-
expect(configuration.getLdapServerProperties()).andReturn(ldapServerProperties);
replay(ldapTemplate, ldapServerProperties, configurationProvider,
configuration);
final AmbariLdapDataPopulatorTestInstance populator = new
AmbariLdapDataPopulatorTestInstance(configurationProvider, users);
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
index b09ac31..3d1385d 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog270Test.java
@@ -28,6 +28,9 @@ import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGUR
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_TABLE;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_INFRA_NEW_NAME;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_INFRA_OLD_NAME;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_SEQUENCES_SEQUENCE_NAME_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_SEQUENCES_SEQUENCE_VALUE_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_SEQUENCES_TABLE;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.COMPONENT_DESIRED_STATE_TABLE;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.COMPONENT_NAME_COLUMN;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.COMPONENT_STATE_TABLE;
@@ -52,6 +55,32 @@ import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.PK_KERBEROS_KEY
import static org.apache.ambari.server.upgrade.UpgradeCatalog270.PK_KKP;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.PK_KKP_MAPPING_SERVICE;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.PRINCIPAL_NAME_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_BASE_URL_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_COMPONENTS_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_DISTRIBUTION_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_FOREIGN_KEY;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_ID_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_MIRRORS_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_PRIMARY_KEY;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_REPO_ID_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_REPO_NAME_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_REPO_OS_ID_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_TABLE;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_DEFINITION_UNIQUE_REPO_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_AMBARI_MANAGED_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_FAMILY_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_FOREIGN_KEY;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_ID_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_PRIMARY_KEY;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_REPO_VERSION_ID_COLUMN;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_OS_TABLE;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_TAGS_FOREIGN_KEY;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_TAGS_REPO_DEFINITION_ID_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_TAGS_TABLE;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_TAGS_TAG_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_VERSION_REPOSITORIES_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_VERSION_REPO_VERSION_ID_COLUMN;
+import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REPO_VERSION_TABLE;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REQUEST_DISPLAY_STATUS_COLUMN;
import static org.apache.ambari.server.upgrade.UpgradeCatalog270.REQUEST_TABLE;
import static
org.apache.ambari.server.upgrade.UpgradeCatalog270.REQUEST_USER_NAME_COLUMN;
@@ -381,6 +410,12 @@ public class UpgradeCatalog270Test {
Capture<DBAccessor.DBColumnInfo> updateUserTableCaptures =
newCapture(CaptureType.ALL);
Capture<DBAccessor.DBColumnInfo> alterUserTableCaptures =
newCapture(CaptureType.ALL);
+ Capture<List<DBAccessor.DBColumnInfo>> addRepoOsTableCapturedColumns =
newCapture(CaptureType.ALL);
+ Capture<List<DBAccessor.DBColumnInfo>>
addRepoDefinitionTableCapturedColumns = newCapture(CaptureType.ALL);
+ Capture<List<DBAccessor.DBColumnInfo>> addRepoTagsTableCapturedColumns =
newCapture(CaptureType.ALL);
+ Capture<String[]> insertAmbariSequencesRowColumns =
newCapture(CaptureType.ALL);
+ Capture<String[]> insertAmbariSequencesRowValues =
newCapture(CaptureType.ALL);
+
// Any return value will work here as long as a SQLException is not thrown.
expect(dbAccessor.getColumnType(USERS_TABLE,
USERS_USER_TYPE_COLUMN)).andReturn(0).anyTimes();
@@ -388,6 +423,9 @@ public class UpgradeCatalog270Test {
prepareUpdateGroupMembershipRecords(dbAccessor,
createMembersTableCaptures);
prepareUpdateAdminPrivilegeRecords(dbAccessor,
createAdminPrincipalTableCaptures);
prepareUpdateUsersTable(dbAccessor, updateUserTableCaptures,
alterUserTableCaptures);
+ prepareUpdateRepoTables(dbAccessor, addRepoOsTableCapturedColumns,
addRepoDefinitionTableCapturedColumns, addRepoTagsTableCapturedColumns,
+ insertAmbariSequencesRowColumns, insertAmbariSequencesRowValues);
+
// upgradeKerberosTables
Capture<List<DBAccessor.DBColumnInfo>> kerberosKeytabColumnsCapture =
newCapture();
dbAccessor.createTable(eq(KERBEROS_KEYTAB_TABLE),
capture(kerberosKeytabColumnsCapture));
@@ -497,6 +535,8 @@ public class UpgradeCatalog270Test {
validateUpdateGroupMembershipRecords(createMembersTableCaptures);
validateUpdateAdminPrivilegeRecords(createAdminPrincipalTableCaptures);
validateUpdateUsersTable(updateUserTableCaptures, alterUserTableCaptures);
+ validateCreateRepoOsTable(addRepoOsTableCapturedColumns,
addRepoDefinitionTableCapturedColumns, addRepoTagsTableCapturedColumns,
+ insertAmbariSequencesRowColumns, insertAmbariSequencesRowValues);
verify(dbAccessor);
}
@@ -678,6 +718,52 @@ public class UpgradeCatalog270Test {
expectLastCall().once();
}
+ private void prepareUpdateRepoTables(DBAccessor dbAccessor,
+ Capture<List<DBAccessor.DBColumnInfo>>
addRepoOsTableCapturedColumns,
+ Capture<List<DBAccessor.DBColumnInfo>>
addRepoDefinitionTableCapturedColumns,
+ Capture<List<DBAccessor.DBColumnInfo>>
addRepoTagsTableCapturedColumns,
+ Capture<String[]>
insertAmbariSequencesRowColumns,
+ Capture<String[]>
insertAmbariSequencesRowValues)
+ throws SQLException {
+
+ dbAccessor.createTable(eq(REPO_OS_TABLE),
capture(addRepoOsTableCapturedColumns));
+ expectLastCall().once();
+ dbAccessor.addPKConstraint(REPO_OS_TABLE, REPO_OS_PRIMARY_KEY,
REPO_OS_ID_COLUMN);
+ expectLastCall().once();
+ dbAccessor.addFKConstraint(REPO_OS_TABLE, REPO_OS_FOREIGN_KEY,
REPO_OS_REPO_VERSION_ID_COLUMN, REPO_VERSION_TABLE,
REPO_VERSION_REPO_VERSION_ID_COLUMN, false);
+ expectLastCall().once();
+
+ dbAccessor.createTable(eq(REPO_DEFINITION_TABLE),
capture(addRepoDefinitionTableCapturedColumns));
+ expectLastCall().once();
+ dbAccessor.addPKConstraint(REPO_DEFINITION_TABLE,
REPO_DEFINITION_PRIMARY_KEY, REPO_DEFINITION_ID_COLUMN);
+ expectLastCall().once();
+ dbAccessor.addFKConstraint(REPO_DEFINITION_TABLE,
REPO_DEFINITION_FOREIGN_KEY, REPO_DEFINITION_REPO_OS_ID_COLUMN, REPO_OS_TABLE,
REPO_OS_ID_COLUMN, false);
+ expectLastCall().once();
+
+ dbAccessor.createTable(eq(REPO_TAGS_TABLE),
capture(addRepoTagsTableCapturedColumns));
+ expectLastCall().once();
+ dbAccessor.addFKConstraint(REPO_TAGS_TABLE, REPO_TAGS_FOREIGN_KEY,
REPO_TAGS_REPO_DEFINITION_ID_COLUMN, REPO_DEFINITION_TABLE,
REPO_DEFINITION_ID_COLUMN, false);
+ expectLastCall().once();
+
+ expect(dbAccessor.tableHasColumn(eq(REPO_VERSION_TABLE),
eq(REPO_VERSION_REPOSITORIES_COLUMN))).andReturn(true).once();
+
+ expect(dbAccessor.getKeyToStringColumnMap(REPO_VERSION_TABLE,
REPO_VERSION_REPO_VERSION_ID_COLUMN, REPO_VERSION_REPOSITORIES_COLUMN, null,
null, true))
+ .andReturn(Collections.emptyMap())
+ .once();
+
+ expect(dbAccessor.insertRowIfMissing(eq(AMBARI_SEQUENCES_TABLE),
+ capture(insertAmbariSequencesRowColumns),
+ capture(insertAmbariSequencesRowValues),
+ eq(false))).andReturn(true).once();
+ expect(dbAccessor.insertRowIfMissing(eq(AMBARI_SEQUENCES_TABLE),
+ capture(insertAmbariSequencesRowColumns),
+ capture(insertAmbariSequencesRowValues),
+ eq(false))).andReturn(true).once();
+
+ dbAccessor.dropColumn(eq(REPO_VERSION_TABLE),
eq(REPO_VERSION_REPOSITORIES_COLUMN));
+ expectLastCall().once();
+ }
+
private void validateUpdateUsersTable(Capture<DBAccessor.DBColumnInfo>
updateUserTableCaptures, Capture<DBAccessor.DBColumnInfo>
alterUserTableCaptures) {
Assert.assertTrue(updateUserTableCaptures.hasCaptured());
validateColumns(updateUserTableCaptures.getValues(),
@@ -698,6 +784,59 @@ public class UpgradeCatalog270Test {
);
}
+ private void
validateCreateRepoOsTable(Capture<List<DBAccessor.DBColumnInfo>>
addRepoOsTableCapturedColumns,
+
Capture<List<DBAccessor.DBColumnInfo>> addRepoDefinitionTableCapturedColumns,
+
Capture<List<DBAccessor.DBColumnInfo>> addRepoTagsTableCapturedColumns,
Capture<String[]> insertAmbariSequencesRowColumns, Capture<String[]>
insertAmbariSequencesRowValues) {
+ Assert.assertTrue(addRepoOsTableCapturedColumns.hasCaptured());
+ validateColumns(addRepoOsTableCapturedColumns.getValue(),
+ Arrays.asList(
+ new DBAccessor.DBColumnInfo(REPO_OS_ID_COLUMN, Long.class, null,
null, false),
+ new DBAccessor.DBColumnInfo(REPO_OS_REPO_VERSION_ID_COLUMN,
Long.class, null, null, false),
+ new DBAccessor.DBColumnInfo(REPO_OS_FAMILY_COLUMN, String.class,
255, null, false),
+ new DBAccessor.DBColumnInfo(REPO_OS_AMBARI_MANAGED_COLUMN,
Integer.class, null, 1, true)
+ )
+ );
+
+ Assert.assertTrue(addRepoDefinitionTableCapturedColumns.hasCaptured());
+ validateColumns(addRepoDefinitionTableCapturedColumns.getValue(),
+ Arrays.asList(
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_ID_COLUMN, Long.class,
null, null, false),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_REPO_OS_ID_COLUMN,
Long.class, null, null, false),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_REPO_NAME_COLUMN,
String.class, 255, null, false),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_REPO_ID_COLUMN,
String.class, 255, null, false),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_BASE_URL_COLUMN,
String.class, 2048, null, true),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_DISTRIBUTION_COLUMN,
String.class, 2048, null, true),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_COMPONENTS_COLUMN,
String.class, 2048, null, true),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_UNIQUE_REPO_COLUMN,
Integer.class, 1, 1, true),
+ new DBAccessor.DBColumnInfo(REPO_DEFINITION_MIRRORS_COLUMN,
String.class, 2048, null, true)
+ )
+ );
+
+ Assert.assertTrue(addRepoTagsTableCapturedColumns.hasCaptured());
+ validateColumns(addRepoTagsTableCapturedColumns.getValue(),
+ Arrays.asList(
+ new DBAccessor.DBColumnInfo(REPO_TAGS_REPO_DEFINITION_ID_COLUMN,
Long.class, null, null, false),
+ new DBAccessor.DBColumnInfo(REPO_TAGS_TAG_COLUMN, String.class,
255, null, false)
+ )
+ );
+
+ List<String[]> values;
+
+ Assert.assertTrue(insertAmbariSequencesRowColumns.hasCaptured());
+ values = insertAmbariSequencesRowColumns.getValues();
+ Assert.assertEquals(2, values.size());
+ Assert.assertArrayEquals(new
String[]{AMBARI_SEQUENCES_SEQUENCE_NAME_COLUMN,
AMBARI_SEQUENCES_SEQUENCE_VALUE_COLUMN}, values.get(0));
+ Assert.assertArrayEquals(new
String[]{AMBARI_SEQUENCES_SEQUENCE_NAME_COLUMN,
AMBARI_SEQUENCES_SEQUENCE_VALUE_COLUMN}, values.get(1));
+
+ Assert.assertTrue(insertAmbariSequencesRowValues.hasCaptured());
+ values = insertAmbariSequencesRowValues.getValues();
+ Assert.assertEquals(2, values.size());
+ Assert.assertArrayEquals(new String[]{"'repo_os_id_seq'", "1"},
values.get(0));
+ Assert.assertArrayEquals(new String[]{"'repo_definition_id_seq'", "1"},
values.get(1));
+
+
+ }
+
private void validateColumns(List<DBAccessor.DBColumnInfo> capturedColumns,
List<DBAccessor.DBColumnInfo> expectedColumns) {
Assert.assertEquals(expectedColumns.size(), capturedColumns.size());
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
index 207e958..f2e1b6a 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
@@ -217,8 +217,6 @@ public class UpgradeTest {
}
}
- schemaUpgradeHelper.startPersistenceService();
-
schemaUpgradeHelper.executePreDMLUpdates(upgradeCatalogs);
schemaUpgradeHelper.executeDMLUpdates(upgradeCatalogs, "test");
@@ -226,8 +224,6 @@ public class UpgradeTest {
schemaUpgradeHelper.executeOnPostUpgrade(upgradeCatalogs);
LOG.info("Upgrade successful.");
-
- schemaUpgradeHelper.stopPersistenceService();
}
private String getLastVersion() throws Exception {
--
To stop receiving notification emails like this one, please contact
[email protected].