You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by db...@apache.org on 2016/06/09 12:24:01 UTC
ambari git commit: AMBARI-16836 : View Instance: Data Migration.
(Nitiraj Rathore via dipayanb)
Repository: ambari
Updated Branches:
refs/heads/branch-2.4 e149d0864 -> a20fd0e26
AMBARI-16836 : View Instance: Data Migration. (Nitiraj Rathore via dipayanb)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/a20fd0e2
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/a20fd0e2
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/a20fd0e2
Branch: refs/heads/branch-2.4
Commit: a20fd0e26e6a9d08a025a3ef6ba7c2092df39f61
Parents: e149d08
Author: Dipayan Bhowmick <di...@gmail.com>
Authored: Thu Jun 9 17:53:44 2016 +0530
Committer: Dipayan Bhowmick <di...@gmail.com>
Committed: Thu Jun 9 17:53:44 2016 +0530
----------------------------------------------------------------------
.../api/services/ViewDataMigrationService.java | 143 ++----------
.../view/ViewDataMigrationContextImpl.java | 44 +++-
.../server/view/ViewDataMigrationUtility.java | 228 +++++++++++++++++++
.../ambari/server/view/ViewExtractor.java | 7 +-
.../apache/ambari/server/view/ViewRegistry.java | 147 +++++++++++-
.../main/python/ambari_server/serverUpgrade.py | 5 -
.../services/ViewDataMigrationServiceTest.java | 178 ++-------------
.../view/ViewDataMigrationContextImplTest.java | 55 ++---
.../view/ViewDataMigrationUtilityTest.java | 184 +++++++++++++++
.../ambari/server/view/ViewRegistryTest.java | 6 +-
10 files changed, 658 insertions(+), 339 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewDataMigrationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewDataMigrationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewDataMigrationService.java
index c6846ce..4a71ce2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewDataMigrationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewDataMigrationService.java
@@ -18,11 +18,9 @@
package org.apache.ambari.server.api.services;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
-import org.apache.ambari.server.view.ViewDataMigrationContextImpl;
+import org.apache.ambari.server.view.ViewDataMigrationUtility;
import org.apache.ambari.server.view.ViewRegistry;
-import org.apache.ambari.view.migration.ViewDataMigrationContext;
import org.apache.ambari.view.migration.ViewDataMigrationException;
-import org.apache.ambari.view.migration.ViewDataMigrator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -31,7 +29,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
-import java.util.Map;
/**
* Service responsible for data migration between view instances.
@@ -57,7 +54,15 @@ public class ViewDataMigrationService extends BaseService {
*/
private final String instanceName;
- private ViewRegistry viewRegistry;
+ /**
+ * The singleton view registry.
+ */
+ ViewRegistry viewRegistry;
+
+ /**
+ * The view data migration utility.
+ */
+ private ViewDataMigrationUtility viewDataMigrationUtility;
/**
* Constructor.
@@ -77,8 +82,8 @@ public class ViewDataMigrationService extends BaseService {
* Migrates view instance persistence data from origin view instance
* specified in the path params.
*
- * @param originViewVersion the origin view version
- * @param originInstanceName the origin view instance name
+ * @param originViewVersion the origin view version
+ * @param originInstanceName the origin view instance name
*/
@PUT
@Path("{originVersion}/{originInstanceName}")
@@ -93,127 +98,25 @@ public class ViewDataMigrationService extends BaseService {
LOG.info("Data Migration to view instance " + viewName + "/" + viewVersion + "/" + instanceName +
" from " + viewName + "/" + originViewVersion + "/" + originInstanceName);
- ViewInstanceEntity instanceDefinition = getViewInstanceEntity(viewName, viewVersion, instanceName);
- ViewInstanceEntity originInstanceDefinition = getViewInstanceEntity(viewName, originViewVersion, originInstanceName);
+ ViewInstanceEntity instanceDefinition = viewRegistry.getInstanceDefinition(
+ viewName, viewVersion, instanceName);
+ ViewInstanceEntity originInstanceDefinition = viewRegistry.getInstanceDefinition(
+ viewName, originViewVersion, originInstanceName);
- ViewDataMigrationContextImpl migrationContext = getViewDataMigrationContext(instanceDefinition, originInstanceDefinition);
-
- ViewDataMigrator dataMigrator = getViewDataMigrator(instanceDefinition, migrationContext);
-
- LOG.debug("Running before-migration hook");
- if (!dataMigrator.beforeMigration()) {
- String msg = "View " + viewName + "/" + viewVersion + "/" + instanceName + " canceled the migration process";
-
- LOG.error(msg);
- throw new ViewDataMigrationException(msg);
- }
-
- Map<String, Class> originClasses = migrationContext.getOriginEntityClasses();
- Map<String, Class> currentClasses = migrationContext.getCurrentEntityClasses();
- for (Map.Entry<String, Class> originEntity : originClasses.entrySet()) {
- LOG.debug("Migrating persistence entity " + originEntity.getKey());
- if (currentClasses.containsKey(originEntity.getKey())) {
- Class entity = currentClasses.get(originEntity.getKey());
- dataMigrator.migrateEntity(originEntity.getValue(), entity);
- } else {
- LOG.debug("Entity " + originEntity.getKey() + " not found in target view");
- dataMigrator.migrateEntity(originEntity.getValue(), null);
- }
- }
-
- LOG.debug("Migrating instance data");
- dataMigrator.migrateInstanceData();
-
- LOG.debug("Running after-migration hook");
- dataMigrator.afterMigration();
-
- LOG.debug("Copying user permissions");
- viewRegistry.copyPrivileges(originInstanceDefinition, instanceDefinition);
+ getViewDataMigrationUtility().migrateData(instanceDefinition, originInstanceDefinition, false);
Response.ResponseBuilder builder = Response.status(Response.Status.OK);
return builder.build();
}
- protected ViewDataMigrationContextImpl getViewDataMigrationContext(ViewInstanceEntity instanceDefinition, ViewInstanceEntity originInstanceDefinition) {
- return new ViewDataMigrationContextImpl(
- originInstanceDefinition, instanceDefinition);
- }
-
- protected ViewInstanceEntity getViewInstanceEntity(String viewName, String viewVersion, String instanceName) {
- return viewRegistry.getInstanceDefinition(viewName, viewVersion, instanceName);
- }
-
- /**
- * Get the migrator instance for view instance with injected migration context.
- * If versions of instances are same returns copy-all-data migrator.
- * If versions are different, loads the migrator from the current view (view should
- * contain ViewDataMigrator implementation, otherwise exception will be raised).
- *
- * @param currentInstanceDefinition the current view instance definition
- * @param migrationContext the migration context to inject into migrator
- * @throws ViewDataMigrationException if view does not support migration
- * @return the data migration instance
- */
- protected ViewDataMigrator getViewDataMigrator(ViewInstanceEntity currentInstanceDefinition,
- ViewDataMigrationContextImpl migrationContext)
- throws ViewDataMigrationException {
- ViewDataMigrator dataMigrator;
-
- LOG.info("Migrating " + viewName + "/" + viewVersion + "/" + instanceName +
- " data from " + migrationContext.getOriginDataVersion() + " to " +
- migrationContext.getCurrentDataVersion() + " data version");
-
- if (migrationContext.getOriginDataVersion() == migrationContext.getCurrentDataVersion()) {
-
- LOG.info("Instances of same version, copying all data.");
- dataMigrator = new CopyAllDataMigrator(migrationContext);
- } else {
- try {
- dataMigrator = currentInstanceDefinition.getDataMigrator(migrationContext);
- if (dataMigrator == null) {
- throw new ViewDataMigrationException("A view instance " +
- viewName + "/" + viewVersion + "/" + instanceName + " does not support migration.");
- }
- LOG.debug("Data migrator loaded");
- } catch (ClassNotFoundException e) {
- String msg = "Caught exception loading data migrator of " + viewName + "/" + viewVersion + "/" + instanceName;
-
- LOG.error(msg, e);
- throw new RuntimeException(msg);
- }
+ protected ViewDataMigrationUtility getViewDataMigrationUtility() {
+ if (viewDataMigrationUtility == null) {
+ viewDataMigrationUtility = new ViewDataMigrationUtility(viewRegistry);
}
- return dataMigrator;
+ return viewDataMigrationUtility;
}
- /**
- * The data migrator implementation that copies all data without modification.
- * Used to copy data between instances of same version.
- */
- public static class CopyAllDataMigrator implements ViewDataMigrator {
- private ViewDataMigrationContext migrationContext;
-
- public CopyAllDataMigrator(ViewDataMigrationContext migrationContext) {
- this.migrationContext = migrationContext;
- }
-
- @Override
- public boolean beforeMigration() {
- return true;
- }
-
- @Override
- public void afterMigration() {
- }
-
- @Override
- public void migrateEntity(Class originEntityClass, Class currentEntityClass)
- throws ViewDataMigrationException {
- migrationContext.copyAllObjects(originEntityClass, currentEntityClass);
- }
-
- @Override
- public void migrateInstanceData() {
- migrationContext.copyAllInstanceData();
- }
+ protected void setViewDataMigrationUtility(ViewDataMigrationUtility viewDataMigrationUtility) {
+ this.viewDataMigrationUtility = viewDataMigrationUtility;
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationContextImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationContextImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationContextImpl.java
index 94e3e28..909b3a1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationContextImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationContextImpl.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.view;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.google.inject.persist.Transactional;
import org.apache.ambari.server.orm.entities.ViewEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
@@ -119,6 +120,7 @@ public class ViewDataMigrationContextImpl implements ViewDataMigrationContext {
}
@Override
+ @Transactional
public void putCurrentInstanceData(String user, String key, String value) {
putInstanceData(currentInstanceDefinition, user, key, value);
}
@@ -135,6 +137,7 @@ public class ViewDataMigrationContextImpl implements ViewDataMigrationContext {
}
@Override
+ @Transactional
public void copyAllObjects(Class originEntityClass, Class currentEntityClass, EntityConverter entityConverter)
throws ViewDataMigrationException {
try{
@@ -209,6 +212,7 @@ public class ViewDataMigrationContextImpl implements ViewDataMigrationContext {
}
@Override
+ @Transactional
public void putOriginInstanceData(String user, String key, String value) {
putInstanceData(originInstanceDefinition, user, key, value);
}
@@ -227,15 +231,37 @@ public class ViewDataMigrationContextImpl implements ViewDataMigrationContext {
* @param value the value
*/
private static void putInstanceData(ViewInstanceEntity instanceDefinition, String user, String name, String value) {
- ViewInstanceDataEntity viewInstanceDataEntity = new ViewInstanceDataEntity();
- viewInstanceDataEntity.setViewName(instanceDefinition.getViewName());
- viewInstanceDataEntity.setViewInstanceName(instanceDefinition.getName());
- viewInstanceDataEntity.setName(name);
- viewInstanceDataEntity.setUser(user);
- viewInstanceDataEntity.setValue(value);
- viewInstanceDataEntity.setViewInstanceEntity(instanceDefinition);
-
- instanceDefinition.getData().add(viewInstanceDataEntity);
+ ViewInstanceDataEntity oldInstanceDataEntity = getInstanceData(instanceDefinition, user, name);
+ if (oldInstanceDataEntity != null) {
+ instanceDefinition.getData().remove(oldInstanceDataEntity);
+ }
+
+ ViewInstanceDataEntity instanceDataEntity = new ViewInstanceDataEntity();
+ instanceDataEntity.setViewName(instanceDefinition.getViewName());
+ instanceDataEntity.setViewInstanceName(instanceDefinition.getName());
+ instanceDataEntity.setName(name);
+ instanceDataEntity.setUser(user);
+ instanceDataEntity.setValue(value);
+ instanceDataEntity.setViewInstanceEntity(instanceDefinition);
+
+ instanceDefinition.getData().add(instanceDataEntity);
+ }
+
+ /**
+ * Get the instance data entity for the given key and user.
+ *
+ * @param user owner of the data
+ * @param key the key
+ * @return the instance data entity associated with the given key and user
+ */
+ private static ViewInstanceDataEntity getInstanceData(ViewInstanceEntity instanceDefinition, String user, String key) {
+ for (ViewInstanceDataEntity viewInstanceDataEntity : instanceDefinition.getData()) {
+ if (viewInstanceDataEntity.getName().equals(key) &&
+ viewInstanceDataEntity.getUser().equals(user)) {
+ return viewInstanceDataEntity;
+ }
+ }
+ return null;
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationUtility.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationUtility.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationUtility.java
new file mode 100644
index 0000000..15318c0
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewDataMigrationUtility.java
@@ -0,0 +1,228 @@
+/**
+ * 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.view;
+
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.view.PersistenceException;
+import org.apache.ambari.view.ViewInstanceDefinition;
+import org.apache.ambari.view.migration.ViewDataMigrationContext;
+import org.apache.ambari.view.migration.ViewDataMigrationException;
+import org.apache.ambari.view.migration.ViewDataMigrator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Map;
+
+/**
+ * Helper class for view data migration.
+ */
+public class ViewDataMigrationUtility {
+
+ /**
+ * The logger.
+ */
+ protected final static Logger LOG = LoggerFactory.getLogger(ViewDataMigrationUtility.class);
+
+ /**
+ * The View Registry.
+ */
+ private ViewRegistry viewRegistry;
+
+ /**
+ * Constructor.
+ * @param viewRegistry the view registry
+ */
+ public ViewDataMigrationUtility(ViewRegistry viewRegistry) {
+ this.viewRegistry = viewRegistry;
+ }
+
+ /**
+ * Migrates data from source to target instance
+ * @param targetInstanceDefinition target instance entity
+ * @param sourceInstanceDefinition source instance entity
+ *
+ * @throws ViewDataMigrationException when view does not support migration or an error during migration occurs.
+ */
+ public void migrateDataOnce(ViewInstanceEntity targetInstanceDefinition, ViewInstanceEntity sourceInstanceDefinition)
+ throws ViewDataMigrationException {
+ ViewDataMigrationContextImpl migrationContext = getViewDataMigrationContext(targetInstanceDefinition, sourceInstanceDefinition);
+ }
+
+ /**
+ * Migrates data from source to target instance
+ * @param targetInstanceDefinition target instance entity
+ * @param sourceInstanceDefinition source instance entity
+ * @param migrateOnce cancel if previously migrated
+ *
+ * @throws ViewDataMigrationException when view does not support migration or an error during migration occurs.
+ */
+ public void migrateData(ViewInstanceEntity targetInstanceDefinition, ViewInstanceEntity sourceInstanceDefinition,
+ boolean migrateOnce)
+ throws ViewDataMigrationException {
+ ViewDataMigrationContextImpl migrationContext = getViewDataMigrationContext(targetInstanceDefinition, sourceInstanceDefinition);
+
+ if (migrateOnce) {
+ if (!isTargetEmpty(migrationContext)) {
+ LOG.error("Migration canceled because target instance is not empty");
+ return;
+ }
+ }
+
+ ViewDataMigrator dataMigrator = getViewDataMigrator(targetInstanceDefinition, migrationContext);
+
+ LOG.debug("Running before-migration hook");
+ if (!dataMigrator.beforeMigration()) {
+ String msg = "View " + targetInstanceDefinition.getInstanceName() + " canceled the migration process";
+
+ LOG.error(msg);
+ throw new ViewDataMigrationException(msg);
+ }
+
+ Map<String, Class> originClasses = migrationContext.getOriginEntityClasses();
+ Map<String, Class> currentClasses = migrationContext.getCurrentEntityClasses();
+ for (Map.Entry<String, Class> originEntity : originClasses.entrySet()) {
+ LOG.debug("Migrating persistence entity " + originEntity.getKey());
+ if (currentClasses.containsKey(originEntity.getKey())) {
+ Class entity = currentClasses.get(originEntity.getKey());
+ dataMigrator.migrateEntity(originEntity.getValue(), entity);
+ } else {
+ LOG.debug("Entity " + originEntity.getKey() + " not found in target view");
+ dataMigrator.migrateEntity(originEntity.getValue(), null);
+ }
+ }
+
+ LOG.debug("Migrating instance data");
+ dataMigrator.migrateInstanceData();
+
+ LOG.debug("Running after-migration hook");
+ dataMigrator.afterMigration();
+
+ LOG.debug("Copying user permissions");
+ viewRegistry.copyPrivileges(sourceInstanceDefinition, targetInstanceDefinition);
+
+ migrationContext.putCurrentInstanceData("upgrade", "upgradedFrom", sourceInstanceDefinition.getViewEntity().getVersion());
+ }
+
+ private boolean isTargetEmpty(ViewDataMigrationContext migrationContext) {
+ if (migrationContext.getCurrentInstanceDataByUser().size() > 0) {
+ return false;
+ }
+
+ try {
+ for (Class entity : migrationContext.getCurrentEntityClasses().values()) {
+ if (migrationContext.getCurrentDataStore().findAll(entity, null).size() > 0) {
+ return false;
+ }
+ }
+ } catch (PersistenceException e) {
+ ViewInstanceDefinition current = migrationContext.getCurrentInstanceDefinition();
+ LOG.error("Persistence exception while check if instance is empty: " +
+ current.getViewDefinition().getViewName() + "{" + current.getViewDefinition().getVersion() + "}/" +
+ current.getInstanceName(), e);
+ }
+
+ return true;
+ }
+
+ /**
+ * Create the data migration context for DataMigrator to access data of current
+ * and origin instances.
+ * @param targetInstanceDefinition target instance definition
+ * @param sourceInstanceDefinition source instance definition
+ * @return data migration context
+ */
+ protected ViewDataMigrationContextImpl getViewDataMigrationContext(ViewInstanceEntity targetInstanceDefinition,
+ ViewInstanceEntity sourceInstanceDefinition) {
+ return new ViewDataMigrationContextImpl(sourceInstanceDefinition, targetInstanceDefinition);
+ }
+
+ /**
+ * Get the migrator instance for view instance with injected migration context.
+ * If versions of instances are same returns copy-all-data migrator.
+ * If versions are different, loads the migrator from the current view (view should
+ * contain ViewDataMigrator implementation, otherwise exception will be raised).
+ *
+ * @param currentInstanceDefinition the current view instance definition
+ * @param migrationContext the migration context to inject into migrator
+ * @throws ViewDataMigrationException if view does not support migration
+ * @return the data migration instance
+ */
+ protected ViewDataMigrator getViewDataMigrator(ViewInstanceEntity currentInstanceDefinition,
+ ViewDataMigrationContextImpl migrationContext)
+ throws ViewDataMigrationException {
+ ViewDataMigrator dataMigrator;
+
+ LOG.info("Migrating " + currentInstanceDefinition.getInstanceName() +
+ " data from " + migrationContext.getOriginDataVersion() + " to " +
+ migrationContext.getCurrentDataVersion() + " data version");
+
+ if (migrationContext.getOriginDataVersion() == migrationContext.getCurrentDataVersion()) {
+
+ LOG.info("Instances of same version, copying all data.");
+ dataMigrator = new CopyAllDataMigrator(migrationContext);
+ } else {
+ try {
+ dataMigrator = currentInstanceDefinition.getDataMigrator(migrationContext);
+ if (dataMigrator == null) {
+ throw new ViewDataMigrationException("A view instance " +
+ currentInstanceDefinition.getInstanceName() + " does not support migration.");
+ }
+ LOG.debug("Data migrator loaded");
+ } catch (ClassNotFoundException e) {
+ String msg = "Caught exception loading data migrator of " + currentInstanceDefinition.getInstanceName();
+
+ LOG.error(msg, e);
+ throw new RuntimeException(msg);
+ }
+ }
+ return dataMigrator;
+ }
+
+
+ /**
+ * The data migrator implementation that copies all data without modification.
+ * Used to copy data between instances of same version.
+ */
+ public static class CopyAllDataMigrator implements ViewDataMigrator {
+ private ViewDataMigrationContext migrationContext;
+
+ public CopyAllDataMigrator(ViewDataMigrationContext migrationContext) {
+ this.migrationContext = migrationContext;
+ }
+
+ @Override
+ public boolean beforeMigration() {
+ return true;
+ }
+
+ @Override
+ public void afterMigration() {
+ }
+
+ @Override
+ public void migrateEntity(Class originEntityClass, Class currentEntityClass)
+ throws ViewDataMigrationException {
+ migrationContext.copyAllObjects(originEntityClass, currentEntityClass);
+ }
+
+ @Override
+ public void migrateInstanceData() {
+ migrationContext.copyAllInstanceData();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
index 3550f98..3425691 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
@@ -19,6 +19,7 @@ package org.apache.ambari.server.view;
import org.apache.ambari.server.orm.entities.ViewEntity;
import org.apache.ambari.server.view.configuration.ViewConfig;
+import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -72,9 +73,13 @@ public class ViewExtractor {
String archivePath = archiveDir.getAbsolutePath();
try {
+ // Remove directory if jar was updated since last extracting
+ if (archiveDir.exists() && viewArchive.lastModified() > archiveDir.lastModified()) {
+ FileUtils.deleteDirectory(archiveDir);
+ }
+
// Skip if the archive has already been extracted
if (!archiveDir.exists()) {
-
String msg = "Creating archive folder " + archivePath + ".";
view.setStatusDetail(msg);
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index bda1079..90144e2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -97,14 +97,17 @@ import org.apache.ambari.view.ViewResourceHandler;
import org.apache.ambari.view.cluster.Cluster;
import org.apache.ambari.view.events.Event;
import org.apache.ambari.view.events.Listener;
+import org.apache.ambari.view.migration.ViewDataMigrationException;
import org.apache.ambari.view.validation.Validator;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
+import javax.xml.bind.JAXBException;
import java.beans.IntrospectionException;
import java.io.File;
import java.io.FileInputStream;
@@ -192,6 +195,11 @@ public class ViewRegistry {
protected final static Logger LOG = LoggerFactory.getLogger(ViewRegistry.class);
/**
+ * View Data Migration Utility
+ */
+ protected ViewDataMigrationUtility viewDataMigrationUtility;
+
+ /**
* View data access object.
*/
@Inject
@@ -305,7 +313,6 @@ public class ViewRegistry {
@Inject
RemoteAmbariClusterDAO remoteAmbariClusterDAO;
-
// ----- Constructors -----------------------------------------------------
/**
@@ -709,12 +716,14 @@ public class ViewRegistry {
}
List<PrivilegeEntity> sourceInstancePrivileges = privilegeDAO.findByResourceId(sourceInstanceEntity.getResource().getId());
- for (PrivilegeEntity privilegeEntity : sourceInstancePrivileges) {
- privilegeDAO.detach(privilegeEntity);
- privilegeEntity.setResource(targetInstanceEntity.getResource());
- privilegeEntity.setId(null);
- privilegeDAO.create(privilegeEntity);
- privilegeEntity.getPrincipal().getPrivileges().add(privilegeEntity);
+ for (PrivilegeEntity sourcePrivilege : sourceInstancePrivileges) {
+ PrivilegeEntity targetPrivilege = new PrivilegeEntity();
+ targetPrivilege.setPrincipal(sourcePrivilege.getPrincipal());
+ targetPrivilege.setResource(targetInstanceEntity.getResource());
+ targetPrivilege.setPermission(sourcePrivilege.getPermission());
+ privilegeDAO.create(targetPrivilege);
+
+ targetPrivilege.getPrincipal().getPrivileges().add(sourcePrivilege);
}
}
@@ -1582,6 +1591,7 @@ public class ViewRegistry {
@Override
public void run() {
readViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile, serverVersion);
+ migrateDataFromPreviousVersion(viewDefinition, serverVersion);
}
});
}
@@ -1593,6 +1603,13 @@ public class ViewRegistry {
}
}
+ for(ViewEntity view : getDefinitions()) {
+ if (view.getStatus() == ViewDefinition.ViewStatus.DEPLOYED) {
+ // migrate views that are not need extraction, for ones that need call will be done in the runnable.
+ migrateDataFromPreviousVersion(view, serverVersion);
+ }
+ }
+
if (useExecutor && extractionRunnables.size() > 0) {
final ExecutorService executorService = getExecutorService(configuration);
@@ -1630,7 +1647,7 @@ public class ViewRegistry {
// extract the archive and get the class loader
ClassLoader cl = extractor.extractViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile);
- configureViewLogging(viewDefinition,cl);
+ configureViewLogging(viewDefinition, cl);
ViewConfig viewConfig = archiveUtility.getViewConfigFromExtractedArchive(extractedArchiveDirPath,
configuration.isViewValidationEnabled());
@@ -1664,6 +1681,39 @@ public class ViewRegistry {
}
}
+ private void migrateDataFromPreviousVersion(ViewEntity viewDefinition, String serverVersion) {
+ if (!viewDefinitions.containsKey(viewDefinition.getName())) { // migrate only registered views to avoid recursive calls
+ LOG.debug("Cancel auto migration of not loaded view: " + viewDefinition.getName() + ".");
+ return;
+ }
+ try {
+
+ for (ViewInstanceEntity instance : viewDefinition.getInstances()) {
+ LOG.debug("Try to migrate the data from previous version of: " + viewDefinition.getName() + "/" +
+ instance.getInstanceName() + ".");
+ ViewInstanceEntity latestUnregisteredView = getLatestUnregisteredInstance(serverVersion, instance);
+
+ if (latestUnregisteredView != null) {
+ String instanceName = instance.getViewEntity().getName() + "/" + instance.getName();
+ try {
+ LOG.info("Found previous version of the view instance " + instanceName + ": " +
+ latestUnregisteredView.getViewEntity().getName() + "/" + latestUnregisteredView.getName());
+ getViewDataMigrationUtility().migrateData(instance, latestUnregisteredView, true);
+ LOG.info("View data migrated: " + viewDefinition.getName() + ".");
+ } catch (ViewDataMigrationException e) {
+ LOG.error("Error occurred during migration", e);
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ String msg = "Caught exception migrating data in view " + viewDefinition.getName();
+
+ setViewStatus(viewDefinition, ViewEntity.ViewStatus.ERROR, msg + " : " + e.getMessage());
+ LOG.error(msg, e);
+ }
+ }
+
/**
* copies non-log4j properties (like ambari.log.dir) from ambari's log4j.properties into view's log4j properties
* and removes log4j specific properties (log4j.rootLogger) inside ambari's log4j.properties from view's log4j properties
@@ -1972,8 +2022,89 @@ public class ViewRegistry {
return url.substring(0,index);
}
+ /**
+ * From all extracted views in the work directory finds ones that are present only in
+ * extracted version (not registered in the registry during startup).
+ * If jar is not exists, that means that this view is previous version of view.
+ * Finds latest between unregistered instances and returns it.
+ *
+ * @param serverVersion server version
+ * @param instance view instance entity
+ * @return latest unregistered instance of same name of same view.
+ */
+ private ViewInstanceEntity getLatestUnregisteredInstance(String serverVersion, ViewInstanceEntity instance)
+ throws JAXBException, IOException, SAXException {
+ File viewDir = configuration.getViewsDir();
+ String extractedArchivesPath = viewDir.getAbsolutePath() +
+ File.separator + EXTRACTED_ARCHIVES_DIR;
+
+ File extractedArchivesDir = new File(extractedArchivesPath);
+ File[] extractedArchives = extractedArchivesDir.listFiles();
+
+ // find all view archives from previous Ambari versions
+ Map<ViewInstanceEntity, Long> unregInstancesTimestamps = new HashMap<>();
+ if (extractedArchives != null) {
+
+ for (File archiveDir : extractedArchives) {
+ if (archiveDir.isDirectory()) {
+ ViewConfig uViewConfig = archiveUtility.getViewConfigFromExtractedArchive(archiveDir.getPath(), false);
+ if (!uViewConfig.isSystem()) {
+ // load prev versions of same view
+ if (!uViewConfig.getName().equals(instance.getViewEntity().getViewName())) {
+ continue;
+ }
+
+ // check if it's not registered yet. It means that jar file is not present while directory in
+ // work dir present, so maybe it's prev version of view.
+ if (viewDefinitions.containsKey(ViewEntity.getViewName(uViewConfig.getName(), uViewConfig.getVersion()))) {
+ continue;
+ }
+
+ LOG.debug("Unregistered extracted view found: " + archiveDir.getPath());
+
+ ViewEntity uViewDefinition = new ViewEntity(uViewConfig, configuration, archiveDir.getPath());
+ readViewArchive(uViewDefinition, archiveDir, archiveDir, serverVersion);
+ for (ViewInstanceEntity instanceEntity : uViewDefinition.getInstances()) {
+ LOG.debug(uViewDefinition.getName() + " instance found: " + instanceEntity.getInstanceName());
+ unregInstancesTimestamps.put(instanceEntity, archiveDir.lastModified());
+ }
+ }
+ }
+ }
+ }
+
+ // Find latest previous version
+ long latestPrevInstanceTimestamp = 0;
+ ViewInstanceEntity latestPrevInstance = null;
+ for (ViewInstanceEntity unregInstance : unregInstancesTimestamps.keySet()) {
+ if (unregInstance.getName().equals(instance.getName())) {
+ if (unregInstancesTimestamps.get(unregInstance) > latestPrevInstanceTimestamp) {
+ latestPrevInstance = unregInstance;
+ latestPrevInstanceTimestamp = unregInstancesTimestamps.get(latestPrevInstance);
+ }
+ }
+ }
+ if (latestPrevInstance != null) {
+ LOG.debug("Previous version of " + instance.getViewEntity().getName() + "/" + instance.getName() + " found: " +
+ latestPrevInstance.getViewEntity().getName() + "/" + latestPrevInstance.getName());
+ } else {
+ LOG.debug("Previous version of " + instance.getViewEntity().getName() + "/" + instance.getName() + " not found");
+ }
+ return latestPrevInstance;
+ }
+
+ protected ViewDataMigrationUtility getViewDataMigrationUtility() {
+ if (viewDataMigrationUtility == null) {
+ viewDataMigrationUtility = new ViewDataMigrationUtility(this);
+ }
+ return viewDataMigrationUtility;
+ }
+
+ protected void setViewDataMigrationUtility(ViewDataMigrationUtility viewDataMigrationUtility) {
+ this.viewDataMigrationUtility = viewDataMigrationUtility;
+ }
/**
* Module for stand alone view registry.
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/main/python/ambari_server/serverUpgrade.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/serverUpgrade.py b/ambari-server/src/main/python/ambari_server/serverUpgrade.py
index 483b79e..8bd7c51 100644
--- a/ambari-server/src/main/python/ambari_server/serverUpgrade.py
+++ b/ambari-server/src/main/python/ambari_server/serverUpgrade.py
@@ -404,11 +404,6 @@ def upgrade(args):
for admin_views_dir in admin_views_dirs:
shutil.rmtree(admin_views_dir)
- # Remove ambari views directory for the rest of the jars, at the time of upgrade. At restart all jars present in Ambari will be extracted into work directory
- views_dir = get_views_dir(properties)
- for views in views_dir:
- shutil.rmtree(views)
-
# check if ambari has obsolete LDAP configuration
if properties.get_property(LDAP_PRIMARY_URL_PROPERTY) and not properties.get_property(IS_LDAP_CONFIGURED):
args.warnings.append("Existing LDAP configuration is detected. You must run the \"ambari-server setup-ldap\" command to adjust existing LDAP configuration.")
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewDataMigrationServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewDataMigrationServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewDataMigrationServiceTest.java
index 1eb7ac2..39b2d96 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewDataMigrationServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewDataMigrationServiceTest.java
@@ -17,21 +17,14 @@
*/
package org.apache.ambari.server.api.services;
-import junit.framework.Assert;
-import org.apache.ambari.server.orm.entities.ViewEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
-import org.apache.ambari.server.view.ViewDataMigrationContextImpl;
+import org.apache.ambari.server.view.ViewDataMigrationUtility;
import org.apache.ambari.server.view.ViewRegistry;
-import org.apache.ambari.view.migration.ViewDataMigrationContext;
-import org.apache.ambari.view.migration.ViewDataMigrationException;
-import org.apache.ambari.view.migration.ViewDataMigrator;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import java.util.Collections;
-import java.util.Map;
+import javax.ws.rs.WebApplicationException;
import static org.easymock.EasyMock.*;
@@ -45,171 +38,38 @@ public class ViewDataMigrationServiceTest {
private static String version1 = "1.0.0";
private static String version2 = "2.0.0";
- private static String xml_view_with_migrator_v2 = "<view>\n" +
- " <name>" + viewName + "</name>\n" +
- " <label>My View!</label>\n" +
- " <version>" + version2 + "</version>\n" +
- " <data-version>1</data-version>\n" +
- " <data-migrator-class>org.apache.ambari.server.api.services.ViewDataMigrationServiceTest$MyDataMigrator</data-migrator-class>\n" +
- " <instance>\n" +
- " <name>" + instanceName + "</name>\n" +
- " <label>My Instance 1!</label>\n" +
- " </instance>\n" +
- "</view>";
-
- private static String xml_view_with_migrator_v1 = "<view>\n" +
- " <name>" + viewName + "</name>\n" +
- " <label>My View!</label>\n" +
- " <version>" + version1 + "</version>\n" +
- " <instance>\n" +
- " <name>" + instanceName + "</name>\n" +
- " <label>My Instance 1!</label>\n" +
- " </instance>\n" +
- "</view>";
-
@Rule
public ExpectedException thrown = ExpectedException.none();
- @Before
- public void setUp() throws Exception {
+ @Test
+ public void testServiceMigrateCallAdmin() throws Exception {
ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
expect(viewRegistry.checkAdmin()).andReturn(true).anyTimes();
- viewRegistry.copyPrivileges(anyObject(ViewInstanceEntity.class), anyObject(ViewInstanceEntity.class));
- expectLastCall().anyTimes();
replay(viewRegistry);
ViewRegistry.initInstance(viewRegistry);
- }
- @Test
- public void testMigrateDataSameVersions() throws Exception {
- TestViewDataMigrationService service = new TestViewDataMigrationService(viewName, version2, instanceName);
+ ViewDataMigrationService service = new ViewDataMigrationService(viewName, version1, instanceName);
- ViewDataMigrationContextImpl context = createNiceMock(ViewDataMigrationContextImpl.class);
- expect(context.getOriginDataVersion()).andReturn(42);
- expect(context.getCurrentDataVersion()).andReturn(42);
- replay(context);
- service.setMigrationContext(context);
+ ViewDataMigrationUtility migrationUtility = createStrictMock(ViewDataMigrationUtility.class);
+ migrationUtility.migrateData(anyObject(ViewInstanceEntity.class), anyObject(ViewInstanceEntity.class), eq(false));
+ replay(migrationUtility);
+ service.setViewDataMigrationUtility(migrationUtility);
- ViewDataMigrator migrator = service.getViewDataMigrator(
- service.getViewInstanceEntity(viewName, version2, instanceName), context);
+ service.migrateData(version2, instanceName);
- Assert.assertTrue(migrator instanceof ViewDataMigrationService.CopyAllDataMigrator);
+ verify(migrationUtility);
}
@Test
- public void testMigrateDataDifferentVersions() throws Exception {
- TestViewDataMigrationService service = new TestViewDataMigrationService(viewName, version2, instanceName);
-
- ViewDataMigrationContextImpl context = getViewDataMigrationContext();
- service.setMigrationContext(context);
-
- ViewDataMigrator migrator = createStrictMock(ViewDataMigrator.class);
- expect(migrator.beforeMigration()).andReturn(true);
- migrator.migrateEntity(anyObject(Class.class), anyObject(Class.class)); expectLastCall();
- migrator.migrateInstanceData(); expectLastCall();
- migrator.afterMigration(); expectLastCall();
-
- replay(migrator);
- service.setMigrator(migrator);
-
- service.migrateData(version1, instanceName);
-
- verify(migrator);
- }
-
- @Test
- public void testMigrateDataDifferentVersionsCancel() throws Exception {
- TestViewDataMigrationService service = new TestViewDataMigrationService(viewName, version2, instanceName);
-
- ViewDataMigrationContextImpl context = getViewDataMigrationContext();
- service.setMigrationContext(context);
-
- ViewDataMigrator migrator = createStrictMock(ViewDataMigrator.class);
- expect(migrator.beforeMigration()).andReturn(false);
-
- replay(migrator);
- service.setMigrator(migrator);
-
- thrown.expect(ViewDataMigrationException.class);
- service.migrateData(version1, instanceName);
- }
-
- private static ViewDataMigrationContextImpl getViewDataMigrationContext() {
- Map<String, Class> entities = Collections.<String, Class>singletonMap("MyEntityClass", Object.class);
- ViewDataMigrationContextImpl context = createNiceMock(ViewDataMigrationContextImpl.class);
- expect(context.getOriginDataVersion()).andReturn(2).anyTimes();
- expect(context.getCurrentDataVersion()).andReturn(1).anyTimes();
- expect(context.getOriginEntityClasses()).andReturn(entities).anyTimes();
- expect(context.getCurrentEntityClasses()).andReturn(entities).anyTimes();
- replay(context);
- return context;
- }
-
- //Migration service that avoids ViewRegistry and DB calls
- private static class TestViewDataMigrationService extends ViewDataMigrationService {
-
- private ViewDataMigrator migrator;
- private ViewDataMigrationContextImpl migrationContext;
-
- public TestViewDataMigrationService(String viewName, String viewVersion, String instanceName) {
- super(viewName, viewVersion, instanceName);
- }
-
- @Override
- protected ViewInstanceEntity getViewInstanceEntity(String viewName, String viewVersion, String instanceName) {
- ViewEntity viewEntity = createNiceMock(ViewEntity.class);
- expect(viewEntity.getViewName()).andReturn(viewName);
- expect(viewEntity.getVersion()).andReturn(viewVersion);
-
- replay(viewEntity);
-
- ViewInstanceEntity instanceEntity = createNiceMock(ViewInstanceEntity.class);
- expect(instanceEntity.getViewEntity()).andReturn(viewEntity);
- expect(instanceEntity.getViewName()).andReturn(viewName);
- expect(instanceEntity.getInstanceName()).andReturn(instanceName);
-
- try {
- ViewDataMigrator mockMigrator;
- if (migrator == null) {
- mockMigrator = createNiceMock(ViewDataMigrator.class);
- } else {
- mockMigrator = migrator;
- }
- expect(instanceEntity.getDataMigrator(anyObject(ViewDataMigrationContext.class))).
- andReturn(mockMigrator);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- replay(instanceEntity);
- return instanceEntity;
- }
-
- @Override
- protected ViewDataMigrationContextImpl getViewDataMigrationContext(ViewInstanceEntity instanceDefinition,
- ViewInstanceEntity originInstanceDefinition) {
- if (migrationContext == null) {
- ViewDataMigrationContextImpl contextMock = createNiceMock(ViewDataMigrationContextImpl.class);
- replay(contextMock);
- return contextMock;
- }
- return migrationContext;
- }
-
- public ViewDataMigrator getMigrator() {
- return migrator;
- }
-
- public void setMigrator(ViewDataMigrator migrator) {
- this.migrator = migrator;
- }
+ public void testServiceMigrateCallNotAdmin() throws Exception {
+ ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+ expect(viewRegistry.checkAdmin()).andReturn(false).anyTimes();
+ replay(viewRegistry);
+ ViewRegistry.initInstance(viewRegistry);
- public ViewDataMigrationContextImpl getMigrationContext() {
- return migrationContext;
- }
+ ViewDataMigrationService service = new ViewDataMigrationService(viewName, version1, instanceName);
- public void setMigrationContext(ViewDataMigrationContextImpl migrationContext) {
- this.migrationContext = migrationContext;
- }
+ thrown.expect(WebApplicationException.class);
+ service.migrateData(version2, instanceName);
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationContextImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationContextImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationContextImplTest.java
index a636e0b..1ae7afb 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationContextImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationContextImplTest.java
@@ -30,9 +30,7 @@ import org.apache.ambari.view.migration.EntityConverter;
import org.easymock.Capture;
import org.junit.Test;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
+import java.util.*;
import static org.easymock.EasyMock.*;
@@ -93,34 +91,27 @@ public class ViewDataMigrationContextImplTest {
ViewEntity entity2 = getViewEntityMock(VERSION_2);
replay(entity1, entity2);
- Capture<ViewInstanceDataEntity> capturedInstanceData1 = Capture.newInstance();
- Collection data1 = createNiceMock(Collection.class);
- expect(data1.add(capture(capturedInstanceData1))).andReturn(true);
- replay(data1);
-
- Capture<ViewInstanceDataEntity> capturedInstanceData2 = Capture.newInstance();
- Collection data2 = createStrictMock(Collection.class);
- expect(data2.add(capture(capturedInstanceData2))).andReturn(true);
- replay(data2);
-
ViewInstanceEntity instanceEntity1 = getViewInstanceEntityMock(entity1);
- expect(instanceEntity1.getData()).andReturn(data1);
+ List<ViewInstanceDataEntity> data1 = new ArrayList<>();
+ expect(instanceEntity1.getData()).andReturn(data1).anyTimes();
ViewInstanceEntity instanceEntity2 = getViewInstanceEntityMock(entity2);
- expect(instanceEntity2.getData()).andReturn(data2);
+ List<ViewInstanceDataEntity> data2 = new ArrayList<>();
+ expect(instanceEntity2.getData()).andReturn(data2).anyTimes();
replay(instanceEntity1, instanceEntity2);
ViewDataMigrationContextImpl context = new TestViewDataMigrationContextImpl(instanceEntity1, instanceEntity2);
context.putOriginInstanceData("user1", "key1", "val1");
context.putCurrentInstanceData("user2", "key2", "val2");
- verify(data2);
- Assert.assertEquals("user1", capturedInstanceData1.getValue().getUser());
- Assert.assertEquals("key1", capturedInstanceData1.getValue().getName());
- Assert.assertEquals("val1", capturedInstanceData1.getValue().getValue());
+ Assert.assertEquals(1, data1.size());
+ Assert.assertEquals("user1", data1.get(0).getUser());
+ Assert.assertEquals("key1", data1.get(0).getName());
+ Assert.assertEquals("val1", data1.get(0).getValue());
- Assert.assertEquals("user2", capturedInstanceData2.getValue().getUser());
- Assert.assertEquals("key2", capturedInstanceData2.getValue().getName());
- Assert.assertEquals("val2", capturedInstanceData2.getValue().getValue());
+ Assert.assertEquals(1, data2.size());
+ Assert.assertEquals("user2", data2.get(0).getUser());
+ Assert.assertEquals("key2", data2.get(0).getName());
+ Assert.assertEquals("val2", data2.get(0).getValue());
}
@Test
@@ -215,26 +206,22 @@ public class ViewDataMigrationContextImplTest {
dataEntity.setName("name1");
dataEntity.setValue("value1");
dataEntity.setUser("user1");
- Collection data1 = Arrays.asList(dataEntity);
-
- Capture<ViewInstanceDataEntity> capturedInstanceData = Capture.newInstance();
- Collection data2 = createStrictMock(Collection.class);
- expect(data2.add(capture(capturedInstanceData))).andReturn(true);
- replay(data2);
+ Collection<ViewInstanceDataEntity> data1 = Arrays.asList(dataEntity);
+ List<ViewInstanceDataEntity> data2 = new ArrayList<>();
ViewInstanceEntity instanceEntity1 = getViewInstanceEntityMock(entity1);
- expect(instanceEntity1.getData()).andReturn(data1);
+ expect(instanceEntity1.getData()).andReturn(data1).anyTimes();
ViewInstanceEntity instanceEntity2 = getViewInstanceEntityMock(entity2);
- expect(instanceEntity2.getData()).andReturn(data2);
+ expect(instanceEntity2.getData()).andReturn(data2).anyTimes();
replay(instanceEntity1, instanceEntity2);
ViewDataMigrationContextImpl context = new TestViewDataMigrationContextImpl(instanceEntity1, instanceEntity2);
context.copyAllInstanceData();
- verify(data2);
- Assert.assertEquals("user1", capturedInstanceData.getValue().getUser());
- Assert.assertEquals("name1", capturedInstanceData.getValue().getName());
- Assert.assertEquals("value1", capturedInstanceData.getValue().getValue());
+ Assert.assertEquals(1, data2.size());
+ Assert.assertEquals("user1", data2.get(0).getUser());
+ Assert.assertEquals("name1", data2.get(0).getName());
+ Assert.assertEquals("value1", data2.get(0).getValue());
}
@Test
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationUtilityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationUtilityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationUtilityTest.java
new file mode 100644
index 0000000..f997589
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewDataMigrationUtilityTest.java
@@ -0,0 +1,184 @@
+/**
+ * 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.view;
+
+import junit.framework.Assert;
+import org.apache.ambari.server.api.services.ViewDataMigrationService;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.view.migration.ViewDataMigrationContext;
+import org.apache.ambari.view.migration.ViewDataMigrationException;
+import org.apache.ambari.view.migration.ViewDataMigrator;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.*;
+
+/**
+ * ViewDataMigrationUtility Tests.
+ */
+public class ViewDataMigrationUtilityTest {
+
+ private static String viewName = "MY_VIEW";
+ private static String instanceName = "INSTANCE1";
+ private static String version1 = "1.0.0";
+ private static String version2 = "2.0.0";
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ ViewRegistry viewRegistry;
+
+ @Before
+ public void setUp() throws Exception {
+ viewRegistry = createNiceMock(ViewRegistry.class);
+ viewRegistry.copyPrivileges(anyObject(ViewInstanceEntity.class), anyObject(ViewInstanceEntity.class));
+ expectLastCall().anyTimes();
+ replay(viewRegistry);
+ ViewRegistry.initInstance(viewRegistry);
+ }
+
+ @Test
+ public void testMigrateDataSameVersions() throws Exception {
+ TestViewDataMigrationUtility migrationUtility = new TestViewDataMigrationUtility(viewRegistry);
+
+ ViewDataMigrationContextImpl context = getViewDataMigrationContext(42, 42);
+ migrationUtility.setMigrationContext(context);
+
+ ViewDataMigrator migrator = migrationUtility.getViewDataMigrator(
+ getInstanceDefinition(viewName, version2, instanceName), context);
+
+ Assert.assertTrue(migrator instanceof ViewDataMigrationUtility.CopyAllDataMigrator);
+ }
+
+ @Test
+ public void testMigrateDataDifferentVersions() throws Exception {
+ TestViewDataMigrationUtility migrationUtility = new TestViewDataMigrationUtility(viewRegistry);
+
+ ViewDataMigrationContextImpl context = getViewDataMigrationContext(2, 1);
+ migrationUtility.setMigrationContext(context);
+
+ ViewDataMigrator migrator = createStrictMock(ViewDataMigrator.class);
+ expect(migrator.beforeMigration()).andReturn(true);
+ migrator.migrateEntity(anyObject(Class.class), anyObject(Class.class)); expectLastCall();
+ migrator.migrateInstanceData(); expectLastCall();
+ migrator.afterMigration(); expectLastCall();
+
+ replay(migrator);
+
+ ViewInstanceEntity targetInstance = getInstanceDefinition(viewName, version2, instanceName, migrator);
+ ViewInstanceEntity sourceInstance = getInstanceDefinition(viewName, version1, instanceName);
+ migrationUtility.migrateData(targetInstance, sourceInstance, false);
+
+ verify(migrator);
+ }
+
+ @Test
+ public void testMigrateDataDifferentVersionsCancel() throws Exception {
+ TestViewDataMigrationUtility migrationUtility = new TestViewDataMigrationUtility(viewRegistry);
+
+ ViewDataMigrationContextImpl context = getViewDataMigrationContext(2, 1);
+ migrationUtility.setMigrationContext(context);
+
+ ViewDataMigrator migrator = createStrictMock(ViewDataMigrator.class);
+ expect(migrator.beforeMigration()).andReturn(false);
+
+ ViewInstanceEntity targetInstance = getInstanceDefinition(viewName, version2, instanceName, migrator);
+ ViewInstanceEntity sourceInstance = getInstanceDefinition(viewName, version1, instanceName);
+
+ thrown.expect(ViewDataMigrationException.class);
+ migrationUtility.migrateData(targetInstance, sourceInstance, false);
+ }
+
+ private static ViewDataMigrationContextImpl getViewDataMigrationContext(int currentVersion, int originVersion) {
+ Map<String, Class> entities = Collections.<String, Class>singletonMap("MyEntityClass", Object.class);
+ ViewDataMigrationContextImpl context = createNiceMock(ViewDataMigrationContextImpl.class);
+ expect(context.getOriginDataVersion()).andReturn(originVersion).anyTimes();
+ expect(context.getCurrentDataVersion()).andReturn(currentVersion).anyTimes();
+ expect(context.getOriginEntityClasses()).andReturn(entities).anyTimes();
+ expect(context.getCurrentEntityClasses()).andReturn(entities).anyTimes();
+
+ expect(context.getCurrentInstanceDataByUser()).andReturn(new HashMap<String, Map<String, String>>());
+ replay(context);
+ return context;
+ }
+
+ private static class TestViewDataMigrationUtility extends ViewDataMigrationUtility {
+ private ViewDataMigrationContextImpl migrationContext;
+
+ public TestViewDataMigrationUtility(ViewRegistry viewRegistry) {
+ super(viewRegistry);
+ }
+
+ @Override
+ protected ViewDataMigrationContextImpl getViewDataMigrationContext(ViewInstanceEntity targetInstanceDefinition,
+ ViewInstanceEntity sourceInstanceDefinition) {
+ if (migrationContext == null) {
+ return super.getViewDataMigrationContext(targetInstanceDefinition, sourceInstanceDefinition);
+ }
+ return migrationContext;
+ }
+
+ public ViewDataMigrationContextImpl getMigrationContext() {
+ return migrationContext;
+ }
+
+ public void setMigrationContext(ViewDataMigrationContextImpl migrationContext) {
+ this.migrationContext = migrationContext;
+ }
+ }
+
+ private ViewInstanceEntity getInstanceDefinition(String viewName, String viewVersion, String instanceName) {
+ ViewDataMigrator migrator = createNiceMock(ViewDataMigrator.class);
+ replay(migrator);
+ return getInstanceDefinition(viewName, viewVersion, instanceName, migrator);
+ }
+
+ private ViewInstanceEntity getInstanceDefinition(String viewName, String viewVersion, String instanceName,
+ ViewDataMigrator migrator) {
+ ViewEntity viewEntity = createNiceMock(ViewEntity.class);
+ expect(viewEntity.getViewName()).andReturn(viewName);
+ expect(viewEntity.getVersion()).andReturn(viewVersion);
+
+ replay(viewEntity);
+
+ ViewInstanceEntity instanceEntity = createNiceMock(ViewInstanceEntity.class);
+ expect(instanceEntity.getViewEntity()).andReturn(viewEntity);
+ expect(instanceEntity.getViewName()).andReturn(viewName);
+ expect(instanceEntity.getInstanceName()).andReturn(instanceName);
+
+ try {
+ expect(instanceEntity.getDataMigrator(anyObject(ViewDataMigrationContext.class))).
+ andReturn(migrator);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ replay(instanceEntity);
+ return instanceEntity;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a20fd0e2/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
index 5b24b19..6b560ee 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
@@ -334,12 +334,12 @@ public class ViewRegistryTest {
jarFiles.put(viewArchive, viewJarFile);
// set expectations
- expect(configuration.getViewsDir()).andReturn(viewDir);
+ expect(configuration.getViewsDir()).andReturn(viewDir).anyTimes();
if (System.getProperty("os.name").contains("Windows")) {
- expect(viewDir.getAbsolutePath()).andReturn("\\var\\lib\\ambari-server\\resources\\views");
+ expect(viewDir.getAbsolutePath()).andReturn("\\var\\lib\\ambari-server\\resources\\views").anyTimes();
}
else {
- expect(viewDir.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views");
+ expect(viewDir.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views").anyTimes();
}
expect(configuration.getViewExtractionThreadPoolCoreSize()).andReturn(2).anyTimes();