Shireesh Anjal has uploaded a new change for review. Change subject: gluster: Add host: Improved gluster validation [2] ......................................................................
gluster: Add host: Improved gluster validation [2] Currently we don't allow to add a host if it has peers. However, if one (or more) of those peers are already part of the cluster in engine DB, then it means that these have been added from gluster CLI and hence the validation should not fail in such cases. Change-Id: I36b3b6d00a71af50ef1b006e95daebfbfe3f67f5 Signed-off-by: Shireesh Anjal <san...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVdsCommand.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/AddVdsCommandTest.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/gluster/GlusterUtil.java M backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/gluster/GlusterUtilTest.java 4 files changed, 61 insertions(+), 19 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/42/14242/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVdsCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVdsCommand.java index 68d8100..a5f84a8 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVdsCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVdsCommand.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import javax.naming.AuthenticationException; @@ -50,6 +51,7 @@ import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.dal.job.ExecutionMessageDirector; +import org.ovirt.engine.core.dao.gluster.GlusterDBUtils; import org.ovirt.engine.core.utils.gluster.GlusterUtil; import org.ovirt.engine.core.utils.ssh.SSHClient; import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil; @@ -383,7 +385,7 @@ sshclient.connect(); sshclient.authenticate(); - return isValidGlusterPeer(sshclient); + return isValidGlusterPeer(sshclient, vds.getVdsGroupId()); } catch (AuthenticationException e) { log.errorFormat( "Failed to authenticate session with host {0}", @@ -411,19 +413,33 @@ /** * Checks if the server can be a valid gluster peer. Fails if it is already part of another cluster (when current - * cluster is not empty). This is done by executing the 'gluster peer status' command on the server.<br> - * Note: In case glusterd is down or not installed on the server (which is a possibility on a new server), the - * command can fail. In such cases, we just log it as a debug message and return true. + * cluster is not empty). This is done by executing the 'gluster peer status' command on the server.<p> + * In case glusterd is down or not installed on the server (which is a possibility on a new server), the command can + * fail. In such cases, we just log it as a debug message and return true.<p> + * Another interesting case is where one of the peers of the server is already present as part of this cluster in + * the engine DB. This means that one ore more hosts were probably added to the gluster cluster using gluster CLI, + * and hence this server should be allowed to be added. * * @param sshclient * SSH client that can be used to execute 'gluster peer status' command on the server + * @param clusterId + * ID of the cluster to which the server is being added. * @return true if the server is good to be added to a gluster cluster, else false. */ - private boolean isValidGlusterPeer(SSHClient sshclient) { + private boolean isValidGlusterPeer(SSHClient sshclient, Guid clusterId) { if (isGlusterSupportEnabled() && clusterHasServers()) { try { // Must not allow adding a server that already is part of another gluster cluster - if (getGlusterUtil().hasPeers(sshclient)) { + Set<String> peers = getGlusterUtil().getPeers(sshclient); + if (peers.size() > 0) { + for(String peer : peers) { + if(getGlusterDBUtils().serverExists(clusterId, peer)) { + // peer present in cluster. so server being added is valid. + return true; + } + } + + // none of the peers present in the cluster. fail with appropriate error. return failCanDoAction(VdcBllMessages.SERVER_ALREADY_PART_OF_ANOTHER_CLUSTER); } } catch (Exception e) { @@ -437,6 +453,10 @@ return true; } + protected GlusterDBUtils getGlusterDBUtils() { + return GlusterDBUtils.getInstance(); + } + protected GlusterUtil getGlusterUtil() { return GlusterUtil.getInstance(); } diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/AddVdsCommandTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/AddVdsCommandTest.java index 93d98d9..cf13de5 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/AddVdsCommandTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/AddVdsCommandTest.java @@ -3,9 +3,12 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; -import static org.mockito.Mockito.when; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + +import java.util.Collections; import org.junit.Before; import org.junit.ClassRule; @@ -23,6 +26,7 @@ import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dao.VdsDAO; import org.ovirt.engine.core.dao.VdsGroupDAO; +import org.ovirt.engine.core.dao.gluster.GlusterDBUtils; import org.ovirt.engine.core.utils.MockConfigRule; import org.ovirt.engine.core.utils.gluster.GlusterUtil; import org.ovirt.engine.core.utils.log.Log; @@ -30,6 +34,7 @@ @RunWith(MockitoJUnitRunner.class) public class AddVdsCommandTest { + private static final String PEER_1 = "peer1"; private static final Guid vdsId = Guid.NewGuid(); private AddVdsActionParameters parameters; @@ -43,6 +48,8 @@ private ClusterUtils clusterUtils; @Mock private GlusterUtil glusterUtil; + @Mock + private GlusterDBUtils glusterDBUtils; @Mock private SSHClient sshClient; @Mock @@ -96,6 +103,7 @@ setupCommonMock(false); } + @SuppressWarnings("unchecked") private void setupGlusterMock(boolean clusterHasServers, VDS upServer, boolean hasPeers) throws Exception { setupCommonMock(true); @@ -104,7 +112,10 @@ doCallRealMethod().when(commandMock).addCanDoActionMessage(any(VdcBllMessages.class)); when(commandMock.getGlusterUtil()).thenReturn(glusterUtil); - when(glusterUtil.hasPeers(any(SSHClient.class))).thenReturn(hasPeers); + when(glusterUtil.getPeers(any(SSHClient.class))).thenReturn(hasPeers ? Collections.singleton(PEER_1) + : Collections.EMPTY_SET); + + when(commandMock.getGlusterDBUtils()).thenReturn(glusterDBUtils); when(clusterUtils.hasServers(any(Guid.class))).thenReturn(clusterHasServers); when(clusterUtils.getUpServer(any(Guid.class))).thenReturn(upServer); @@ -127,13 +138,16 @@ @Test public void canDoActionSucceedsWhenHasPeersThrowsException() throws Exception { setupGlusterMock(true, new VDS(), true); - when(glusterUtil.hasPeers(any(SSHClient.class))).thenThrow(new RuntimeException()); + when(glusterUtil.getPeers(any(SSHClient.class))).thenThrow(new RuntimeException()); + assertTrue(commandMock.canDoAction()); } @Test public void canDoActionFailsWhenGlusterServerHasPeers() throws Exception { setupGlusterMock(true, new VDS(), true); + when(glusterDBUtils.serverExists(any(Guid.class), eq(PEER_1))).thenReturn(false); + assertFalse(commandMock.canDoAction()); assertTrue(commandMock.getReturnValue() .getCanDoActionMessages() @@ -141,6 +155,14 @@ } @Test + public void canDoActionSucceedsWhenGlusterServerHasPeersThatExistInDB() throws Exception { + setupGlusterMock(true, new VDS(), true); + when(glusterDBUtils.serverExists(any(Guid.class), eq(PEER_1))).thenReturn(true); + + assertTrue(commandMock.canDoAction()); + } + + @Test public void canDoActionSucceedsWhenGlusterServerHasNoPeers() throws Exception { setupGlusterMock(true, new VDS(), false); assertTrue(commandMock.canDoAction()); diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/gluster/GlusterUtil.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/gluster/GlusterUtil.java index 9c68173..748fcc2 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/gluster/GlusterUtil.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/gluster/GlusterUtil.java @@ -68,17 +68,17 @@ } /** - * Given an SSHClient (already connected and authenticated), execute the "gluster peer status" command, check if the - * server has any peers and return true if it has at least one. Note that this method does <b>not</b> close the - * connection, and it is the responsibility of the calling code to do the same. + * Given an SSHClient (already connected and authenticated), execute the "gluster peer status" command, and return + * the set of the peers returned by the command. Note that this method does <b>not</b> close the connection, and it + * is the responsibility of the calling code to do the same. * * @param client * The already connected and authenticated SSHClient object - * @return true if the server has at least one peer, else false + * @return Set of peers of the server */ - public boolean hasPeers(SSHClient client) { + public Set<String> getPeers(SSHClient client) { String serversXml = executePeerStatusCommand(client); - return extractServers(serversXml).size() > 0; + return extractServers(serversXml); } /** diff --git a/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/gluster/GlusterUtilTest.java b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/gluster/GlusterUtilTest.java index cdd57ca..ac09698 100644 --- a/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/gluster/GlusterUtilTest.java +++ b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/gluster/GlusterUtilTest.java @@ -3,9 +3,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import java.util.Map; @@ -82,12 +81,13 @@ @Test public void testHasPeersTrue() { - assertTrue(glusterUtil.hasPeers(client)); + assertNotNull(glusterUtil.getPeers(client)); + assertEquals(2, glusterUtil.getPeers(client).size()); } @Test public void testHasPeersFalse() { doReturn(OUTPUT_XML_NO_PEERS).when(glusterUtil).executePeerStatusCommand(client); - assertFalse(glusterUtil.hasPeers(client)); + assertTrue(glusterUtil.getPeers(client).isEmpty()); } } -- To view, visit http://gerrit.ovirt.org/14242 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I36b3b6d00a71af50ef1b006e95daebfbfe3f67f5 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Shireesh Anjal <san...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches