package org.ovirt.engine.api.restapi.resource.gluster;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.ovirt.engine.api.restapi.resource.gluster.GlusterTestHelper.brickDir;
import static org.ovirt.engine.api.restapi.resource.gluster.GlusterTestHelper.clusterId;
import static org.ovirt.engine.api.restapi.resource.gluster.GlusterTestHelper.serverId;
import static org.ovirt.engine.api.restapi.resource.gluster.GlusterTestHelper.volumeId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.junit.Test;
import org.ovirt.engine.api.model.Action;
import org.ovirt.engine.api.model.Cluster;
import org.ovirt.engine.api.model.Fault;
import org.ovirt.engine.api.model.GlusterBrick;
import org.ovirt.engine.api.model.GlusterBricks;
import org.ovirt.engine.api.model.GlusterVolume;
import org.ovirt.engine.api.resource.ClusterResource;
import org.ovirt.engine.api.restapi.resource.AbstractBackendCollectionResourceTest;
import org.ovirt.engine.api.restapi.resource.AbstractBackendResource;
import org.ovirt.engine.api.restapi.resource.BackendResource;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.gluster.GlusterVolumeBricksActionParameters;
import org.ovirt.engine.core.common.action.gluster.GlusterVolumeRemoveBricksParameters;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity;
import org.ovirt.engine.core.common.queries.IdQueryParameters;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.queries.gluster.GlusterVolumeAdvancedDetailsParameters;
import org.ovirt.engine.core.compat.Guid;
public class BackendGlusterBricksResourceTest extends AbstractBackendCollectionResourceTest<GlusterBrick, GlusterBrickEntity, BackendGlusterBricksResource> {
private static final String serverName = "testServer";
private BackendGlusterVolumeResource parentMock;
private GlusterTestHelper helper;
private static final String MIGRATE_BRICKS_ACTION_BASE_URL = "/clusters/" + clusterId + "/glustervolumes/" + volumeId;
public BackendGlusterBricksResourceTest() {
super(new BackendGlusterBricksResource(),
null,
null);
}
/**
* Override init to perform additional mocking required for the "list" method of the collection resource.
*/
@Override
protected void init() {
super.init();
setUpParentMocks();
helper = new GlusterTestHelper();
}
@Override
protected List<GlusterBrick> getCollection() {
return collection.list().getGlusterBricks();
}
@Override
protected GlusterBrickEntity getEntity(int index) {
return helper.getBrickEntity(index, false);
}
@Override
@Test
public void testList() throws Exception {
setUpBricksQueryExpectations(null);
UriInfo uriInfo = setUpActionsUriExpectations();
collection.setUriInfo(uriInfo);
verifyCollection(getCollection());
}
@Test
public void testListAllDetails() throws Exception {
setUpBricksQueryExpectations(null);
setUpGetEntityExpectationsAllContent(false);
UriInfo uriInfo = setUpActionsUriExpectations();
collection.setUriInfo(uriInfo);
verifyCollection(getCollection());
}
@Override
@Test
public void testListFailure() throws Exception {
setUpBricksQueryExpectations(FAILURE);
UriInfo uriInfo = setUpUriExpectations(null);
collection.setUriInfo(uriInfo);
try {
getCollection();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
assertTrue(wae.getResponse().getEntity() instanceof Fault);
assertEquals(mockl10n(FAILURE), ((Fault) wae.getResponse().getEntity()).getDetail());
}
}
@Override
@Test
public void testListCrash() throws Exception {
Throwable t = new RuntimeException(FAILURE);
setUpBricksQueryExpectations(t);
UriInfo uriInfo = setUpUriExpectations(null);
collection.setUriInfo(uriInfo);
try {
getCollection();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, BACKEND_FAILED_SERVER_LOCALE, t);
}
}
@Override
@Test
public void testListCrashClientLocale() throws Exception {
UriInfo uriInfo = setUpUriExpectations(null);
locales.add(CLIENT_LOCALE);
Throwable t = new RuntimeException(FAILURE);
setUpBricksQueryExpectations(t);
collection.setUriInfo(uriInfo);
try {
getCollection();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, BACKEND_FAILED_CLIENT_LOCALE, t);
} finally {
locales.clear();
}
}
@Test
public void testAdd() throws Exception {
UriInfo uriInfo = setUpBasicUriExpectations();
when(uriInfo.getPath()).thenReturn("clusters/" + clusterId + "/glustervolumes/" + volumeId + "/bricks");
setUriInfo(uriInfo);
setUpBrickCreationExpectation(false);
Response response = collection.add(createModel());
assertEquals(201, response.getStatus());
assertTrue(response.getEntity() instanceof GlusterBricks);
verifyModel(((GlusterBricks) response.getEntity()).getGlusterBricks().get(0), 0);
}
@Test
public void testAddForce() throws Exception {
UriInfo uriInfo = setUpBasicUriExpectations();
when(uriInfo.getPath()).thenReturn("clusters/" + clusterId + "/glustervolumes/" + volumeId + "/bricks");
setUriInfo(setUpGetMatrixConstraintsExpectations(
BackendResource.FORCE_CONSTRAINT,
true,
"true",
uriInfo
));
setUpBrickCreationExpectation(true);
Response response = collection.add(createModel());
assertEquals(201, response.getStatus());
assertTrue(response.getEntity() instanceof GlusterBricks);
verifyModel(((GlusterBricks) response.getEntity()).getGlusterBricks().get(0), 0);
}
@Test
public void testAddForceFalse() throws Exception {
UriInfo uriInfo = setUpBasicUriExpectations();
when(uriInfo.getPath()).thenReturn("clusters/" + clusterId + "/glustervolumes/" + volumeId + "/bricks");
setUriInfo(setUpGetMatrixConstraintsExpectations(
BackendResource.FORCE_CONSTRAINT,
false,
"false",
uriInfo
));
setUpBrickCreationExpectation(false);
Response response = collection.add(createModel());
assertEquals(201, response.getStatus());
assertTrue(response.getEntity() instanceof GlusterBricks);
verifyModel(((GlusterBricks) response.getEntity()).getGlusterBricks().get(0), 0);
}
private void setUpBrickCreationExpectation(boolean force) {
setUpCreationExpectations(VdcActionType.AddBricksToGlusterVolume,
GlusterVolumeBricksActionParameters.class,
new String[] { "VolumeId", "Bricks", "Force" },
new Object[] { volumeId, getBricks(), force },
true,
true,
getBrickIds(),
VdcQueryType.GetGlusterBrickById,
IdQueryParameters.class,
new String[] { "Id" },
new Object[] { GUIDS[0] },
getEntity(0));
}
@Test
public void testRemove() throws Exception {
setUpGetEntityExpectations(VdcQueryType.GetGlusterVolumeById,
IdQueryParameters.class,
new String[] { "Id" },
new Object[] { volumeId },
helper.getVolumeEntity(0));
setUriInfo(setUpActionExpectations(VdcActionType.GlusterVolumeRemoveBricks,
GlusterVolumeRemoveBricksParameters.class,
new String[] { "VolumeId", "Bricks" },
new Object[] { volumeId, getBrickEntitiesToRemove() },
true,
true));
Action action = new Action();
action.setBricks(getBrickModelsToRemove());
verifyRemove(collection.remove(action));
}
@Test
public void testRemoveCommit() throws Exception {
setUpGetEntityExpectations(VdcQueryType.GetGlusterVolumeById,
IdQueryParameters.class,
new String[] { "Id" },
new Object[] { volumeId },
helper.getVolumeEntity(1));
setUriInfo(setUpActionExpectations(VdcActionType.CommitRemoveGlusterVolumeBricks,
GlusterVolumeRemoveBricksParameters.class,
new String[] {},
new Object[] {},
true,
true));
Action action = new Action();
action.setBricks(getBrickModelsToRemove());
verifyRemove(collection.remove(action));
}
@Test
public void testMigrate() throws Exception {
GlusterBrick brick = new GlusterBrick();
GlusterVolume volume = new GlusterVolume();
brick.setName(serverName + ":" + brickDir);
volume.setId(volumeId.toString());
brick.setGlusterVolume(volume);
GlusterBricks bricks = mock(GlusterBricks.class);
when(bricks.getGlusterBricks()).thenReturn(Collections.singletonList(brick));
setUriInfo(setUpActionExpectations(VdcActionType.StartRemoveGlusterVolumeBricks,
GlusterVolumeRemoveBricksParameters.class,
new String[] {},
new Object[] {},
true,
true));
Action action = new Action();
action.setBricks(bricks);
collection.migrate(action);
}
@Test
public void testStopMigrate() throws Exception {
GlusterBrick brick = new GlusterBrick();
GlusterVolume volume = new GlusterVolume();
brick.setName(serverName + ":" + brickDir);
volume.setId(volumeId.toString());
brick.setGlusterVolume(volume);
GlusterBricks bricks = mock(GlusterBricks.class);
when(bricks.getGlusterBricks()).thenReturn(Collections.singletonList(brick));
setUriInfo(setUpActionExpectations(VdcActionType.StopRemoveGlusterVolumeBricks,
GlusterVolumeRemoveBricksParameters.class,
new String[] {},
new Object[] {},
true,
true));
Action action = new Action();
action.setBricks(bricks);
collection.stopMigrate(action);
}
@Test
public void testActivate() throws Exception {
GlusterBrick brick = new GlusterBrick();
GlusterVolume volume = new GlusterVolume();
brick.setName(serverName + ":" + brickDir);
volume.setId(volumeId.toString());
brick.setGlusterVolume(volume);
GlusterBricks bricks = mock(GlusterBricks.class);
when(bricks.getGlusterBricks()).thenReturn(Collections.singletonList(brick));
setUriInfo(setUpActionExpectations(VdcActionType.StopRemoveGlusterVolumeBricks,
GlusterVolumeRemoveBricksParameters.class,
new String[] {},
new Object[] {},
true,
true));
Action action = new Action();
action.setBricks(bricks);
collection.stopMigrate(action);
}
/**
* Overriding this as the bricks collection doesn't support search queries
*/
@Override
@Test
public void testQuery() throws Exception {
testList();
}
private List<Guid> getBrickIds() {
List<Guid> brickIds = new ArrayList<>();
brickIds.add(GUIDS[0]);
return brickIds;
}
private List<GlusterBrickEntity> getBrickEntitiesToRemove() {
List<GlusterBrickEntity> bricks = new ArrayList<>();
GlusterBrickEntity brick = new GlusterBrickEntity();
brick.setId(GUIDS[0]);
brick.setVolumeId(volumeId);
bricks.add(brick);
return bricks;
}
private GlusterBricks getBrickModelsToRemove() {
GlusterBricks bricks = new GlusterBricks();
GlusterBrick brick = new GlusterBrick();
brick.setId(GUIDS[0].toString());
bricks.getGlusterBricks().add(brick);
return bricks;
}
private List<GlusterBrickEntity> getBricks() {
List<GlusterBrickEntity> bricks = new ArrayList<>();
GlusterBrickEntity brick = new GlusterBrickEntity();
brick.setId(GUIDS[0]);
brick.setServerId(serverId);
brick.setServerName(serverName);
brick.setVolumeId(volumeId);
brick.setBrickDirectory(brickDir);
bricks.add(brick);
return bricks;
}
/**
* Overridden as {@link GlusterBrickEntity} does not have name/description field
*/
@Override
protected void verifyModel(GlusterBrick model, int index) {
assertEquals(GUIDS[index].toString(), model.getId());
assertEquals(volumeId.toString(), model.getGlusterVolume().getId());
assertEquals(serverId.toString(), model.getServerId());
assertEquals(brickDir, model.getBrickDir());
verifyLinks(model);
}
private GlusterBricks createModel() {
GlusterBricks bricks = new GlusterBricks();
GlusterBrick brick = new GlusterBrick();
brick.setId(GUIDS[0].toString());
brick.setGlusterVolume(new GlusterVolume());
brick.getGlusterVolume().setId(volumeId.toString());
brick.setServerId(serverId.toString());
brick.setBrickDir(brickDir);
bricks.getGlusterBricks().add(brick);
return bricks;
}
/**
* The method {@link BackendGlusterBricksResource#list()} internally invokes
* {@link BackendGlusterVolumeResource#get()} to fetch the volume object, and then invokes the query to fetch the
* bricks of that volume. This method mocks the volume resource to return pre-defined volume id
*/
private void setUpParentMocks() {
GlusterVolume volume = new GlusterVolume();
volume.setId(volumeId.toString());
Cluster cluster = new Cluster();
cluster.setId(clusterId.toString());
volume.setCluster(cluster);
ClusterResource clusterResourceMock = mock(ClusterResource.class);
when(clusterResourceMock.get()).thenReturn(cluster);
BackendGlusterVolumesResource volumesResourceMock = mock(BackendGlusterVolumesResource.class);
when(volumesResourceMock.getParent()).thenReturn(clusterResourceMock);
parentMock = mock(BackendGlusterVolumeResource.class);
when(parentMock.getParent()).thenReturn(volumesResourceMock);
when(parentMock.get()).thenReturn(volume);
collection.setParent(parentMock);
doAnswer(invocation -> {
GlusterVolume model = (GlusterVolume) invocation.getArguments()[0];
Cluster clusterModel = new Cluster();
clusterModel.setId(clusterId.toString());
model.setCluster(clusterModel);
model.setId(volumeId.toString());
return model;
}).when(parentMock).addParents(isA(GlusterVolume.class));
}
private void setUpBricksQueryExpectations(Object failure) {
VdcQueryReturnValue queryResult = mock(VdcQueryReturnValue.class);
when(queryResult.getSucceeded()).thenReturn(failure == null);
List<GlusterBrickEntity> entities = new ArrayList<>();
if (failure == null) {
for (int i = 0; i < NAMES.length; i++) {
entities.add(getEntity(i));
}
when(queryResult.getReturnValue()).thenReturn(entities);
} else {
if (failure instanceof String) {
when(queryResult.getExceptionString()).thenReturn((String) failure);
setUpL10nExpectations((String) failure);
} else if (failure instanceof Exception) {
when(backend.runQuery(eq(VdcQueryType.GetGlusterVolumeBricks), any(IdQueryParameters.class))).thenThrow((Exception) failure);
return;
}
}
when(backend.runQuery(eq(VdcQueryType.GetGlusterVolumeBricks), any(IdQueryParameters.class))).thenReturn(
queryResult);
}
private void setUpGetEntityExpectationsAllContent(boolean notFound) throws Exception {
List<String> populateValue = new ArrayList<>();
populateValue.add("true");
when(httpHeaders.getRequestHeader(AbstractBackendResource.POPULATE)).thenReturn(populateValue);
setupEntityExpectationAdvancedDetails(NAMES.length, notFound);
}
private void setupEntityExpectationAdvancedDetails(int times, boolean notFound) throws Exception {
while (times-- > 0) {
setUpGetEntityExpectations(VdcQueryType.GetGlusterVolumeById,
IdQueryParameters.class,
new String[] { "Id" },
new Object[] { volumeId },
helper.getVolumeEntity(0));
setUpGetEntityExpectations(VdcQueryType.GetGlusterVolumeAdvancedDetails,
GlusterVolumeAdvancedDetailsParameters.class,
new String[] { "ClusterId", "VolumeId", "BrickId", "DetailRequired" },
new Object[] { clusterId, volumeId, GUIDS[times], true },
notFound ? null : helper.getVolumeAdvancedDetailsEntity());
}
}
private UriInfo setUpActionsUriExpectations() {
UriInfo uriInfo = setUpBasicUriExpectations(MIGRATE_BRICKS_ACTION_BASE_URL);
return uriInfo;
}
}