You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2015/11/07 15:53:05 UTC
ambari git commit: AMBARI-13741. API call to delete service fails
with error: integrity constraint violated - child record found (Sebastian
Toader via smohanty)
Repository: ambari
Updated Branches:
refs/heads/trunk 079293935 -> 66e2eb424
AMBARI-13741. API call to delete service fails with error: integrity constraint violated - child record found (Sebastian Toader via smohanty)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/66e2eb42
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/66e2eb42
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/66e2eb42
Branch: refs/heads/trunk
Commit: 66e2eb424bd8d8e6611f518b66a3dcd44ae9948e
Parents: 0792939
Author: Sumit Mohanty <sm...@hortonworks.com>
Authored: Sat Nov 7 06:51:07 2015 -0800
Committer: Sumit Mohanty <sm...@hortonworks.com>
Committed: Sat Nov 7 06:51:07 2015 -0800
----------------------------------------------------------------------
.../orm/entities/ClusterServiceEntity.java | 2 +-
.../ServiceComponentDesiredStateEntity.java | 4 +-
.../server/state/cluster/ClusterImpl.java | 35 +++++-
.../svccomphost/ServiceComponentHostImpl.java | 6 ++
.../server/state/cluster/ClusterImplTest.java | 106 ++++++++++++++++++-
5 files changed, 144 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/66e2eb42/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
index d34e2d5..eade294 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
@@ -52,7 +52,7 @@ public class ClusterServiceEntity {
@OneToOne(mappedBy = "clusterServiceEntity", cascade = CascadeType.ALL)
private ServiceDesiredStateEntity serviceDesiredStateEntity;
- @OneToMany(mappedBy = "clusterServiceEntity")
+ @OneToMany(mappedBy = "clusterServiceEntity", cascade = CascadeType.ALL)
private Collection<ServiceComponentDesiredStateEntity> serviceComponentDesiredStateEntities;
public Long getClusterId() {
http://git-wip-us.apache.org/repos/asf/ambari/blob/66e2eb42/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
index 4195710..c39ecc4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
@@ -66,10 +66,10 @@ public class ServiceComponentDesiredStateEntity {
@JoinColumns({@javax.persistence.JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false), @JoinColumn(name = "service_name", referencedColumnName = "service_name", nullable = false)})
private ClusterServiceEntity clusterServiceEntity;
- @OneToMany(mappedBy = "serviceComponentDesiredStateEntity", cascade = CascadeType.PERSIST)
+ @OneToMany(mappedBy = "serviceComponentDesiredStateEntity", cascade = CascadeType.ALL)
private Collection<HostComponentStateEntity> hostComponentStateEntities;
- @OneToMany(mappedBy = "serviceComponentDesiredStateEntity")
+ @OneToMany(mappedBy = "serviceComponentDesiredStateEntity", cascade = CascadeType.ALL)
private Collection<HostComponentDesiredStateEntity> hostComponentDesiredStateEntities;
public Long getClusterId() {
http://git-wip-us.apache.org/repos/asf/ambari/blob/66e2eb42/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index 898aa33..c9ffee0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -37,6 +37,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.persistence.RollbackException;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.ConfigGroupNotFoundException;
import org.apache.ambari.server.DuplicateResourceException;
@@ -1919,9 +1921,8 @@ public class ClusterImpl implements Cluster {
}
for (Service service : services.values()) {
- service.delete();
+ deleteService(service);
}
-
services.clear();
} finally {
clusterGlobalLock.writeLock().unlock();
@@ -1943,13 +1944,41 @@ public class ClusterImpl implements Cluster {
+ ", clusterName=" + getClusterName()
+ ", serviceName=" + service.getName());
}
- service.delete();
+ deleteService(service);
services.remove(serviceName);
+
} finally {
clusterGlobalLock.writeLock().unlock();
}
}
+ /**
+ * Deletes the specified service also removes references to it from {@link this.serviceComponentHosts}
+ * and references to ServiceComponentHost objects that belong to the service from {@link this.serviceComponentHostsByHost}
+ * <p>
+ * Note: This method must be called only with write lock acquired.
+ * </p>
+ * @param service the service to be deleted
+ * @throws AmbariException
+ * @see ServiceComponentHost
+ */
+ private void deleteService(Service service) throws AmbariException {
+ final String serviceName = service.getName();
+
+ service.delete();
+
+ serviceComponentHosts.remove(serviceName);
+
+ for (List<ServiceComponentHost> serviceComponents: serviceComponentHostsByHost.values()){
+ Iterables.removeIf(serviceComponents, new Predicate<ServiceComponentHost>() {
+ @Override
+ public boolean apply(ServiceComponentHost serviceComponentHost) {
+ return serviceComponentHost.getServiceName().equals(serviceName);
+ }
+ });
+ }
+ }
+
@Override
public boolean canBeRemoved() {
loadServices();
http://git-wip-us.apache.org/repos/asf/ambari/blob/66e2eb42/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
index c0804ff..7b1c6ca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
@@ -1373,6 +1373,12 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
try {
if (persisted) {
removeEntities();
+
+ // host must be re-loaded from db to refresh the cached JPA HostEntity
+ // that references HostComponentDesiredStateEntity
+ // and HostComponentStateEntity JPA entities
+ host.refresh();
+
persisted = false;
fireRemovalEvent = true;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/66e2eb42/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
index 39431ed..178adc5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
@@ -18,19 +18,52 @@
package org.apache.ambari.server.state.cluster;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
import org.apache.ambari.server.controller.AmbariSessionManager;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.StackId;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Test;
-
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
public class ClusterImplTest {
+ private static Injector injector;
+ private static Clusters clusters;
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ Injector injector = Guice.createInjector(new InMemoryDefaultTestModule());
+ injector.getInstance(GuiceJpaInitializer.class);
+ clusters = injector.getInstance(Clusters.class);
+ }
+
@Test
public void testAddSessionAttributes() throws Exception {
Map<String, Object> attributes = new HashMap<String, Object>();
@@ -156,4 +189,71 @@ public class ClusterImplTest {
verify(sessionManager, cluster);
}
+
+ @Test
+ public void testDeleteService() throws Exception {
+ // Given
+ String serviceToDelete = "TEZ";
+
+ String clusterName = "TEST_CLUSTER";
+ String hostName1 = "HOST1", hostName2 = "HOST2";
+
+ clusters.addCluster(clusterName, new StackId("HDP-2.1.1"));
+
+ Cluster cluster = clusters.getCluster(clusterName);
+
+ clusters.addHost(hostName1);
+ clusters.addHost(hostName2);
+
+ Host host1 = clusters.getHost(hostName1);
+ host1.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
+ host1.persist();
+
+ Host host2 = clusters.getHost(hostName2);
+ host2.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
+ host2.persist();
+
+ clusters.mapHostsToCluster(Sets.newHashSet(hostName1, hostName2), clusterName);
+
+ Service hdfs = cluster.addService("HDFS");
+ hdfs.persist();
+
+ ServiceComponent nameNode = hdfs.addServiceComponent("NAMENODE");
+ nameNode.persist();
+ nameNode.addServiceComponentHost(hostName1).persist();
+
+ ServiceComponent dataNode = hdfs.addServiceComponent("DATANODE");
+ dataNode.persist();
+ dataNode.addServiceComponentHost(hostName1).persist();
+ dataNode.addServiceComponentHost(hostName2).persist();
+
+ ServiceComponent hdfsClient = hdfs.addServiceComponent("HDFS_CLIENT");
+ hdfsClient.persist();
+ hdfsClient.addServiceComponentHost(hostName1).persist();
+ hdfsClient.addServiceComponentHost(hostName2).persist();
+
+ Service tez = cluster.addService(serviceToDelete);
+ tez.persist();
+
+ ServiceComponent tezClient = tez.addServiceComponent("TEZ_CLIENT");
+ tezClient.persist();
+ ServiceComponentHost tezClientHost1 = tezClient.addServiceComponentHost(hostName1);
+ tezClientHost1.persist();
+ ServiceComponentHost tezClientHost2 = tezClient.addServiceComponentHost(hostName2);
+ tezClientHost2.persist();
+
+ // When
+ cluster.deleteService(serviceToDelete);
+
+ // Then
+ assertFalse("Deleted service should be removed from the service collection !", cluster.getServices().containsKey(serviceToDelete));
+
+ assertEquals("All components of the deleted service should be removed from all hosts", 0, cluster.getServiceComponentHosts(serviceToDelete, null).size());
+
+ boolean checkHost1 = !cluster.getServiceComponentHosts(hostName1).contains(tezClientHost1);
+ boolean checkHost2 = !cluster.getServiceComponentHosts(hostName2).contains(tezClientHost2);
+
+ assertTrue("All components of the deleted service should be removed from all hosts", checkHost1 && checkHost2);
+
+ }
}
\ No newline at end of file