/**
* 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.orm;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.RollbackException;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.H2DatabaseCleaner;
import org.apache.ambari.server.Role;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.orm.dao.ClusterDAO;
import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
import org.apache.ambari.server.orm.dao.HostDAO;
import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
import org.apache.ambari.server.orm.dao.RequestDAO;
import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
import org.apache.ambari.server.orm.dao.StackDAO;
import org.apache.ambari.server.orm.dao.StageDAO;
import org.apache.ambari.server.orm.entities.ClusterEntity;
import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
import org.apache.ambari.server.orm.entities.RequestEntity;
import org.apache.ambari.server.orm.entities.ResourceEntity;
import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
import org.apache.ambari.server.orm.entities.StackEntity;
import org.apache.ambari.server.orm.entities.StageEntity;
import org.apache.ambari.server.security.authorization.ResourceType;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class TestOrmImpl extends Assert {
private static final Logger log = LoggerFactory.getLogger(TestOrmImpl.class);
@Inject
private Injector injector;
@Inject
private StackDAO stackDAO;
@Inject
private ResourceTypeDAO resourceTypeDAO;
@Inject
private ClusterDAO clusterDAO;
@Inject
private OrmTestHelper ormTestHelper;
@Inject
private ClusterServiceDAO clusterServiceDAO;
@Inject
private HostRoleCommandDAO hostRoleCommandDAO;
@Inject
private HostDAO hostDAO;
@Inject
private StageDAO stageDAO;
@Inject
private EntityManager entityManager;
@Inject
private RequestDAO requestDAO;
@Before
public void setup() {
injector = Guice.createInjector(new InMemoryDefaultTestModule());
injector.getInstance(GuiceJpaInitializer.class);
injector.injectMembers(this);
// required to load stack information into the DB
injector.getInstance(AmbariMetaInfo.class);
ormTestHelper.createDefaultData();
}
@After
public void teardown() throws AmbariException, SQLException {
H2DatabaseCleaner.clearDatabaseAndStopPersistenceService(injector);
}
/**
* persistence provider is responsible for returning empty collection if relation doesn't exists
*/
@Test
public void testEmptyPersistentCollection() {
String testClusterName = "test_cluster2";
// create an admin resource to represent this cluster
ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findById(ResourceType.CLUSTER.getId());
if (resourceTypeEntity == null) {
resourceTypeEntity = new ResourceTypeEntity();
resourceTypeEntity.setId(ResourceType.CLUSTER.getId());
resourceTypeEntity.setName(ResourceType.CLUSTER.name());
resourceTypeEntity = resourceTypeDAO.merge(resourceTypeEntity);
}
StackEntity stackEntity = stackDAO.find("HDP", "2.2.0");
ResourceEntity resourceEntity = new ResourceEntity();
resourceEntity.setResourceType(resourceTypeEntity);
ClusterEntity clusterEntity = new ClusterEntity();
clusterEntity.setClusterName(testClusterName);
clusterEntity.setResource(resourceEntity);
clusterEntity.setDesiredStack(stackEntity);
clusterDAO.create(clusterEntity);
clusterEntity = clusterDAO.findByName(clusterEntity.getClusterName());
assertTrue("empty relation wasn't instantiated", clusterEntity.getHostEntities() != null);
}
/**
* Transaction marked for rollback should not be allowed for commit
* @throws Throwable
*/
@Test(expected = RollbackException.class)
public void testRollbackException() throws Throwable{
ormTestHelper.performTransactionMarkedForRollback();
}
/**
* Rollback test
*/
@Test
public void testSafeRollback() {
String testClusterName = "don't save";
EntityManager entityManager = ormTestHelper.getEntityManager();
entityManager.getTransaction().begin();
ClusterEntity clusterEntity = new ClusterEntity();
clusterEntity.setClusterName(testClusterName);
entityManager.persist(clusterEntity);
entityManager.getTransaction().rollback();
assertNull("transaction was not rolled back", clusterDAO.findByName(testClusterName));
}
/**
* Test auto incremented field and custom query example
*/
@Test
public void testAutoIncrementedField() {
Date currentTime = new Date();
String serviceName = "MapReduce1";
String clusterName = "test_cluster1";
createService(currentTime, serviceName, clusterName);
ClusterServiceEntity clusterServiceEntity = clusterServiceDAO.findByClusterAndServiceNames(clusterName, serviceName);
clusterServiceDAO.remove(clusterServiceEntity);
assertNull(clusterServiceDAO.findByClusterAndServiceNames(clusterName, serviceName));
}
private void createService(Date currentTime, String serviceName, String clusterName) {
ClusterEntity cluster = clusterDAO.findByName(clusterName);
ClusterServiceEntity clusterServiceEntity = new ClusterServiceEntity();
clusterServiceEntity.setClusterEntity(cluster);
clusterServiceEntity.setServiceName(serviceName);
cluster.getClusterServiceEntities().add(clusterServiceEntity);
clusterServiceDAO.create(clusterServiceEntity);
clusterDAO.merge(cluster);
clusterServiceEntity = clusterServiceDAO.findByClusterAndServiceNames(clusterName, serviceName);
assertNotNull(clusterServiceEntity);
clusterServiceDAO.merge(clusterServiceEntity);
}
/**
* to clarify: are cascade operations allowed?
*/
@Test
public void testCascadeRemoveFail() {
Date currentTime = new Date();
String serviceName = "MapReduce2";
String clusterName = "test_cluster1";
createService(currentTime, serviceName, clusterName);
ClusterServiceEntity clusterServiceEntity = clusterServiceDAO.findByClusterAndServiceNames(clusterName, serviceName);
clusterServiceDAO.remove(clusterServiceEntity);
Assert.assertNull(
clusterServiceDAO.findByClusterAndServiceNames(clusterName,
serviceName));
}
@Test
public void testSortedCommands() {
injector.getInstance(OrmTestHelper.class).createStageCommands();
HostRoleCommandDAO hostRoleCommandDAO = injector.getInstance(HostRoleCommandDAO.class);
HostDAO hostDAO = injector.getInstance(HostDAO.class);
StageDAO stageDAO = injector.getInstance(StageDAO.class);
List<HostRoleCommandEntity> list =
hostRoleCommandDAO.findSortedCommandsByStageAndHost(
stageDAO.findByActionId("1-1"), hostDAO.findByName("test_host1"));
log.info("command '{}' - taskId '{}' ", list.get(0).getRoleCommand(),
list.get(0).getTaskId());
log.info("command '{}' - taskId '{}'", list.get(1).getRoleCommand(),
list.get(1).getTaskId());
assertTrue(list.get(0).getTaskId() < list.get(1).getTaskId());
}
@Test
public void testFindHostsByStage() {
ormTestHelper.createStageCommands();
StageEntity stageEntity = stageDAO.findByActionId("1-1");
log.info("StageEntity {} {}" + stageEntity.getRequestId() + " "
+ stageEntity.getStageId());
List<HostEntity> hosts = hostDAO.findByStage(stageEntity);
assertEquals(2, hosts.size());
}
@Test
public void testAbortHostRoleCommands() {
ormTestHelper.createStageCommands();
int result = hostRoleCommandDAO.updateStatusByRequestId(
1L, HostRoleStatus.ABORTED, Arrays.asList(HostRoleStatus.QUEUED,
HostRoleStatus.IN_PROGRESS, HostRoleStatus.PENDING));
//result always 1 in batch mode
List<HostRoleCommandEntity> commandEntities = hostRoleCommandDAO.findByRequest(1L);
int count = 0;
for (HostRoleCommandEntity commandEntity : commandEntities) {
if (commandEntity.getStatus() == HostRoleStatus.ABORTED) {
count++;
}
}
assertEquals("Exactly two commands should be in aborted state", 2, count);
}
@Test
public void testFindStageByHostRole() {
ormTestHelper.createStageCommands();
List<HostRoleCommandEntity> list = hostRoleCommandDAO.findByHostRole("test_host1", 1L, 1L, Role.DATANODE.toString());
assertEquals(1, list.size());
}
@Test
public void testLastRequestId() {
ormTestHelper.createStageCommands();
RequestDAO requestDAO = injector.getInstance(RequestDAO.class);
RequestEntity requestEntity = requestDAO.findByPK(1L);
List<StageEntity> stageEntities = new ArrayList<>();
StageEntity stageEntity = new StageEntity();
stageEntity.setClusterId(clusterDAO.findByName("test_cluster1").getClusterId());
stageEntity.setRequest(requestEntity);
stageEntity.setStageId(2L);
stageDAO.create(stageEntity);
StageEntity stageEntity2 = new StageEntity();
stageEntity2.setClusterId(clusterDAO.findByName("test_cluster1").getClusterId());
stageEntity2.setRequest(requestEntity);
stageEntity2.setRequestId(1L);
stageEntity2.setStageId(3L);
stageDAO.create(stageEntity2);
stageEntities.add(stageEntity);
stageEntities.add(stageEntity2);
requestEntity.setStages(stageEntities);
requestDAO.merge(requestEntity);
assertEquals(1L, stageDAO.getLastRequestId());
}
@Test
public void testConcurrentModification() throws InterruptedException {
final StackEntity stackEntity = stackDAO.find("HDP", "2.2.0");
// create an admin resource to represent this cluster
ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findById(ResourceType.CLUSTER.getId());
if (resourceTypeEntity == null) {
resourceTypeEntity = new ResourceTypeEntity();
resourceTypeEntity.setId(ResourceType.CLUSTER.getId());
resourceTypeEntity.setName(ResourceType.CLUSTER.name());
resourceTypeEntity = resourceTypeDAO.merge(resourceTypeEntity);
}
ResourceEntity resourceEntity = new ResourceEntity();
resourceEntity.setResourceType(resourceTypeEntity);
ClusterEntity clusterEntity = new ClusterEntity();
clusterEntity.setClusterName("cluster1");
clusterEntity.setResource(resourceEntity);
clusterEntity.setDesiredStack(stackEntity);
clusterDAO.create(clusterEntity);
clusterEntity = clusterDAO.findById(clusterEntity.getClusterId());
assertEquals("cluster1", clusterEntity.getClusterName());
Thread thread = new Thread(){
@Override
public void run() {
ClusterEntity clusterEntity1 = clusterDAO.findByName("cluster1");
clusterEntity1.setClusterName("anotherName");
clusterDAO.merge(clusterEntity1);
clusterEntity1 = clusterDAO.findById(clusterEntity1.getClusterId());
assertEquals("anotherName", clusterEntity1.getClusterName());
entityManager.clear();
}
};
thread.start();
thread.join();
entityManager.clear();
clusterEntity = clusterDAO.findById(clusterEntity.getClusterId());
assertEquals("anotherName", clusterEntity.getClusterName());
thread = new Thread(){
@Override
public void run() {
clusterDAO.removeByName("anotherName");
entityManager.clear();
}
};
thread.start();
thread.join();
entityManager.clear();
assertNull(clusterDAO.findById(clusterEntity.getClusterId()));
List<ClusterEntity> result = clusterDAO.findAll();
final ResourceTypeEntity finalResourceTypeEntity = resourceTypeEntity;
thread = new Thread(){
@Override
public void run() {
ResourceEntity resourceEntity = new ResourceEntity();
resourceEntity.setResourceType(finalResourceTypeEntity);
ClusterEntity temp = new ClusterEntity();
temp.setClusterName("temp_cluster");
temp.setResource(resourceEntity);
temp.setDesiredStack(stackEntity);
clusterDAO.create(temp);
}
};
thread.start();
thread.join();
assertEquals(result.size() + 1, (result = clusterDAO.findAll()).size());
thread = new Thread(){
@Override
public void run() {
ResourceEntity resourceEntity = new ResourceEntity();
resourceEntity.setResourceType(finalResourceTypeEntity);
ClusterEntity temp = new ClusterEntity();
temp.setClusterName("temp_cluster2");
temp.setResource(resourceEntity);
temp.setDesiredStack(stackEntity);
clusterDAO.create(temp);
}
};
thread.start();
thread.join();
assertEquals(result.size() + 1, (clusterDAO.findAll()).size());
}
}