package org.ovirt.engine.api.restapi.resource;
import java.math.BigDecimal;
import java.util.ArrayList;
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.Boot;
import org.ovirt.engine.api.model.BootDevice;
import org.ovirt.engine.api.model.CdRom;
import org.ovirt.engine.api.model.CdRoms;
import org.ovirt.engine.api.model.Cluster;
import org.ovirt.engine.api.model.Display;
import org.ovirt.engine.api.model.DisplayType;
import org.ovirt.engine.api.model.File;
import org.ovirt.engine.api.model.Floppies;
import org.ovirt.engine.api.model.Floppy;
import org.ovirt.engine.api.model.Host;
import org.ovirt.engine.api.model.OperatingSystem;
import org.ovirt.engine.api.model.Statistic;
import org.ovirt.engine.api.model.CreationStatus;
import org.ovirt.engine.api.model.StorageDomain;
import org.ovirt.engine.api.model.Ticket;
import org.ovirt.engine.api.model.VM;
import org.ovirt.engine.api.model.VmPlacementPolicy;
import org.ovirt.engine.core.common.action.ChangeVMClusterParameters;
import org.ovirt.engine.core.common.action.HibernateVmParameters;
import org.ovirt.engine.core.common.action.MigrateVmParameters;
import org.ovirt.engine.core.common.action.MigrateVmToServerParameters;
import org.ovirt.engine.core.common.action.MoveVmParameters;
import org.ovirt.engine.core.common.action.RemoveVmFromPoolParameters;
import org.ovirt.engine.core.common.action.RunVmOnceParams;
import org.ovirt.engine.core.common.action.SetVmTicketParameters;
import org.ovirt.engine.core.common.action.ShutdownVmParameters;
import org.ovirt.engine.core.common.action.StopVmParameters;
import org.ovirt.engine.core.common.action.StopVmTypeEnum;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VmManagementParametersBase;
import org.ovirt.engine.core.common.businessentities.AsyncTaskStatus;
import org.ovirt.engine.core.common.businessentities.AsyncTaskStatusEnum;
import org.ovirt.engine.core.common.businessentities.BootSequence;
import org.ovirt.engine.core.common.businessentities.VmOsType;
import org.ovirt.engine.core.common.businessentities.storage_domains;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VmStatistics;
import org.ovirt.engine.core.common.interfaces.SearchType;
import org.ovirt.engine.core.common.queries.GetVdsByNameParameters;
import org.ovirt.engine.core.common.queries.GetVmByVmIdParameters;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.common.action.VmOperationParameterBase;
import static org.ovirt.engine.api.restapi.resource.BackendVmsResourceTest.getModel;
import static org.ovirt.engine.api.restapi.resource.BackendVmsResourceTest.setUpEntityExpectations;
import static org.ovirt.engine.api.restapi.resource.BackendVmsResourceTest.setUpStatisticalEntityExpectations;
import static org.ovirt.engine.api.restapi.resource.BackendVmsResourceTest.verifyModelSpecific;
public class BackendVmResourceTest
extends AbstractBackendSubResourceTest<VM, org.ovirt.engine.core.common.businessentities.VM, BackendVmResource> {
private static final String ISO_ID = "foo.iso";
private static final String FLOPPY_ID = "bar.vfd";
public BackendVmResourceTest() {
super(new BackendVmResource(GUIDS[0].toString(), new BackendVmsResource()));
}
@Test
public void testBadGuid() throws Exception {
control.replay();
try {
new BackendVmResource("foo", new BackendVmsResource());
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyNotFoundException(wae);
}
}
@Test
public void testGetNotFound() throws Exception {
setUriInfo(setUpBasicUriExpectations());
setUpGetEntityExpectations(1, true);
control.replay();
try {
resource.get();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyNotFoundException(wae);
}
}
@Test
public void testGet() throws Exception {
setUriInfo(setUpBasicUriExpectations());
setUpGetEntityExpectations(1);
control.replay();
verifyModel(resource.get(), 0);
}
@Test
public void testGetIncludeStatistics() throws Exception {
try {
accepts.add("application/xml; detail=statistics");
setUriInfo(setUpBasicUriExpectations());
setUpGetEntityExpectations(1);
control.replay();
VM vm = resource.get();
assertTrue(vm.isSetStatistics());
verifyModel(vm, 0);
} finally {
accepts.clear();
}
}
@Test
public void testUpdateNotFound() throws Exception {
setUriInfo(setUpBasicUriExpectations());
setUpGetEntityExpectations(1, true);
control.replay();
try {
resource.update(getModel(0));
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyNotFoundException(wae);
}
}
@Test
public void testUpdate() throws Exception {
setUpGetEntityExpectations(2);
setUriInfo(setUpActionExpectations(VdcActionType.UpdateVm,
VmManagementParametersBase.class,
new String[] {},
new Object[] {},
true,
true));
verifyModel(resource.update(getModel(0)), 0);
}
@Test
public void testUpdateVmPolicy() throws Exception {
setUpGetEntityExpectations(2);
setUpGetEntityExpectations("Hosts: name=" + NAMES[1],
SearchType.VDS,
getHost());
setUriInfo(setUpActionExpectations(VdcActionType.UpdateVm,
VmManagementParametersBase.class,
new String[] {},
new Object[] {},
true,
true));
VM model = getModel(0);
model.setPlacementPolicy(new VmPlacementPolicy());
model.getPlacementPolicy().setHost(new Host());
model.getPlacementPolicy().getHost().setName(NAMES[1]);
verifyModel(resource.update(model), 0);
}
private VDS getHost() {
VDS vds = new VDS();
vds.setvds_id(GUIDS[2]);
return vds;
}
@Test
public void testUpdateMovingCluster() throws Exception {
setUpGetEntityExpectations(3);
setUriInfo(setUpActionExpectations(VdcActionType.ChangeVMCluster,
ChangeVMClusterParameters.class,
new String[] {"ClusterId", "VmId"},
new Object[] {GUIDS[1], GUIDS[0]},
true,
true,
false));
setUpActionExpectations(VdcActionType.UpdateVm,
VmManagementParametersBase.class,
new String[] {},
new Object[] {},
true,
true);
VM model = getModel(0);
model.setId(GUIDS[0].toString());
model.setCluster(new Cluster());
model.getCluster().setId(GUIDS[1].toString());
verifyModelOnNewCluster(resource.update(model), 0);
}
@Test
public void testUpdateCantDo() throws Exception {
doTestBadUpdate(false, true, CANT_DO);
}
@Test
public void testUpdateFailed() throws Exception {
doTestBadUpdate(true, false, FAILURE);
}
private void doTestBadUpdate(boolean canDo, boolean success, String detail) throws Exception {
setUpGetEntityExpectations(1);
setUriInfo(setUpActionExpectations(VdcActionType.UpdateVm,
VmManagementParametersBase.class,
new String[] {},
new Object[] {},
canDo,
success));
try {
resource.update(getModel(0));
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, detail);
}
}
@Test
public void testConflictedUpdate() throws Exception {
setUpGetEntityExpectations(1);
setUriInfo(setUpBasicUriExpectations());
control.replay();
VM model = getModel(1);
model.setId(GUIDS[1].toString());
try {
resource.update(model);
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyImmutabilityConstraint(wae);
}
}
@Test
public void testStart() throws Exception {
setUpWindowsGetEntityExpectations(1, false);
setUriInfo(setUpActionExpectations(VdcActionType.RunVmOnce,
RunVmOnceParams.class,
new String[] { "VmId" },
new Object[] { GUIDS[0] }));
verifyActionResponse(resource.start(new Action()));
}
@Test
public void testStartWithPauseAndStateless() throws Exception {
setUpWindowsGetEntityExpectations(1, false);
setUriInfo(setUpActionExpectations(VdcActionType.RunVmOnce,
RunVmOnceParams.class,
new String[] { "VmId", "RunAndPause", "RunAsStateless" },
new Object[] { GUIDS[0], true, Boolean.TRUE }));
Action action = new Action();
action.setPause(true);
action.setVm(new VM());
action.getVm().setStateless(true);
verifyActionResponse(resource.start(action));
}
@Test
public void testStartWithVnc() throws Exception {
setUpWindowsGetEntityExpectations(1, false);
setUriInfo(setUpActionExpectations(VdcActionType.RunVmOnce,
RunVmOnceParams.class,
new String[] { "VmId", "UseVnc" },
new Object[] { GUIDS[0], Boolean.TRUE }));
Action action = new Action();
action.setVm(new VM());
action.getVm().setDisplay(new Display());
action.getVm().getDisplay().setType(DisplayType.VNC.value());
verifyActionResponse(resource.start(action));
}
@Test
public void testStartWithBootDev() throws Exception {
setUpWindowsGetEntityExpectations(1, false);
setUriInfo(setUpActionExpectations(VdcActionType.RunVmOnce,
RunVmOnceParams.class,
new String[] { "VmId", "BootSequence" },
new Object[] { GUIDS[0], BootSequence.N }));
Action action = new Action();
action.setVm(new VM());
action.getVm().setOs(new OperatingSystem());
action.getVm().getOs().getBoot().add(new Boot());
action.getVm().getOs().getBoot().get(0).setDev(BootDevice.NETWORK.value());
verifyActionResponse(resource.start(action));
}
@Test
public void testStartWithCdRomAndFloppy() throws Exception {
setUpWindowsGetEntityExpectations(1, false);
setUriInfo(setUpActionExpectations(VdcActionType.RunVmOnce,
RunVmOnceParams.class,
new String[] { "VmId", "DiskPath", "FloppyPath" },
new Object[] { GUIDS[0], ISO_ID, FLOPPY_ID }));
Action action = new Action();
action.setVm(new VM());
action.getVm().setCdroms(new CdRoms());
action.getVm().getCdroms().getCdRoms().add(new CdRom());
action.getVm().getCdroms().getCdRoms().get(0).setFile(new File());
action.getVm().getCdroms().getCdRoms().get(0).getFile().setId(ISO_ID);
action.getVm().setFloppies(new Floppies());
action.getVm().getFloppies().getFloppies().add(new Floppy());
action.getVm().getFloppies().getFloppies().get(0).setFile(new File());
action.getVm().getFloppies().getFloppies().get(0).getFile().setId(FLOPPY_ID);
verifyActionResponse(resource.start(action));
}
@Test
public void testStartWithHostId() throws Exception {
Host host = new Host();
host.setId(GUIDS[1].toString());
testStartWithHost(host, GUIDS[1]);
}
@Test
public void testStartWithHostName() throws Exception {
setUpGetHostIdExpectations(1);
Host host = new Host();
host.setName(NAMES[1]);
testStartWithHost(host, GUIDS[1]);
}
protected void testStartWithHost(Host host, Guid hostId) throws Exception {
setUpWindowsGetEntityExpectations(1, false);
setUriInfo(setUpActionExpectations(VdcActionType.RunVmOnce,
RunVmOnceParams.class,
new String[] { "VmId", "DestinationVdsId" },
new Object[] { GUIDS[0], hostId }));
Action action = new Action();
action.setVm(new VM());
VmPlacementPolicy placementPolicy = new VmPlacementPolicy();
placementPolicy.setHost(host);
action.getVm().setPlacementPolicy(placementPolicy);
verifyActionResponse(resource.start(action));
}
@Test
public void testSuspend() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.HibernateVm,
HibernateVmParameters.class,
new String[] { "VmId" },
new Object[] { GUIDS[0] }));
verifyActionResponse(resource.suspend(new Action()));
}
@Test
public void testSuspendAsyncPending() throws Exception {
doTestSuspendAsync(AsyncTaskStatusEnum.init, CreationStatus.PENDING);
}
@Test
public void testSuspendAsyncInProgress() throws Exception {
doTestSuspendAsync(AsyncTaskStatusEnum.running, CreationStatus.IN_PROGRESS);
}
@Test
public void testSuspendAsyncFinished() throws Exception {
doTestSuspendAsync(AsyncTaskStatusEnum.finished, CreationStatus.COMPLETE);
}
private void doTestSuspendAsync(AsyncTaskStatusEnum asyncStatus, CreationStatus actionStatus) throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.HibernateVm,
HibernateVmParameters.class,
new String[] { "VmId" },
new Object[] { GUIDS[0] },
asList(GUIDS[1]),
asList(new AsyncTaskStatus(asyncStatus))));
Response response = resource.suspend(new Action());
verifyActionResponse(response, "vms/" + GUIDS[0], true, null, null);
Action action = (Action)response.getEntity();
assertTrue(action.isSetStatus());
assertEquals(actionStatus.value(), action.getStatus().getState());
}
@Test
public void testShutdown() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.ShutdownVm,
ShutdownVmParameters.class,
new String[] { "VmId" },
new Object[] { GUIDS[0] }));
verifyActionResponse(resource.shutdown(new Action()));
}
@Test
public void testStop() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.StopVm,
StopVmParameters.class,
new String[] { "VmId", "StopVmType" },
new Object[] { GUIDS[0], StopVmTypeEnum.NORMAL }));
verifyActionResponse(resource.stop(new Action()));
}
@Test
public void testCancelMigration() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.CancelMigrateVm,
VmOperationParameterBase.class,
new String[] { "VmId" },
new Object[] { GUIDS[0] }));
verifyActionResponse(resource.cancelMigration(new Action()));
}
@Test
public void testDetach() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.RemoveVmFromPool,
RemoveVmFromPoolParameters.class,
new String[] { "VmId" },
new Object[] { GUIDS[0] }));
verifyActionResponse(resource.detach(new Action()));
}
@Test
public void testTicket() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.SetVmTicket,
SetVmTicketParameters.class,
new String[] { "VmId", "Ticket" },
new Object[] { GUIDS[0], NAMES[1] }));
Action action = new Action();
action.setTicket(new Ticket());
action.getTicket().setValue(NAMES[1]);
verifyActionResponse(resource.ticket(action));
}
@Test
public void testMigrateWithHostId() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.MigrateVmToServer,
MigrateVmToServerParameters.class,
new String[] { "VmId", "VdsId", "ForceMigrationForNonMigratableVM" },
new Object[] { GUIDS[0], GUIDS[1], Boolean.FALSE }));
Action action = new Action();
action.setHost(new Host());
action.getHost().setId(GUIDS[1].toString());
verifyActionResponse(resource.migrate(action));
}
@Test
public void testMigrateWithHostName() throws Exception {
setUpGetHostIdExpectations(1);
setUriInfo(setUpActionExpectations(VdcActionType.MigrateVmToServer,
MigrateVmToServerParameters.class,
new String[] { "VmId", "VdsId", "ForceMigrationForNonMigratableVM" },
new Object[] { GUIDS[0], GUIDS[1], Boolean.FALSE }));
Action action = new Action();
action.setHost(new Host());
action.getHost().setName(NAMES[1]);
verifyActionResponse(resource.migrate(action));
}
@Test
public void testMigrateNoHost() throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.MigrateVm,
MigrateVmParameters.class,
new String[] { "VmId", "ForceMigrationForNonMigratableVM" },
new Object[] { GUIDS[0], Boolean.FALSE }));
verifyActionResponse(resource.migrate(new Action()));
}
@Test
public void testExport() throws Exception {
testExportWithStorageDomainId(false, false);
}
@Test
public void testExportWithParams() throws Exception {
testExportWithStorageDomainId(true, true);
}
@Test
public void testExportWithStorageDomainName() throws Exception {
setUpGetEntityExpectations("Storage: name=" + NAMES[2],
SearchType.StorageDomain,
getStorageDomain(2));
StorageDomain storageDomain = new StorageDomain();
storageDomain.setName(NAMES[2]);
doTestExport(storageDomain, false, false);
}
protected void testExportWithStorageDomainId(boolean exclusive, boolean discardSnapshots) throws Exception {
StorageDomain storageDomain = new StorageDomain();
storageDomain.setId(GUIDS[2].toString());
doTestExport(storageDomain, exclusive, discardSnapshots);
}
protected void doTestExport(StorageDomain storageDomain,
boolean exclusive,
boolean discardSnapshots) throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.ExportVm,
MoveVmParameters.class,
new String[] { "ContainerId", "StorageDomainId", "ForceOverride", "CopyCollapse" },
new Object[] { GUIDS[0], GUIDS[2], exclusive, discardSnapshots }));
Action action = new Action();
action.setStorageDomain(storageDomain);
if (exclusive) {
action.setExclusive(exclusive);
}
if (discardSnapshots) {
action.setDiscardSnapshots(discardSnapshots);
}
verifyActionResponse(resource.export(action));
}
@Test
public void testIncompleteExport() throws Exception {
setUriInfo(setUpBasicUriExpectations());
try {
control.replay();
resource.export(new Action());
fail("expected WebApplicationException on incomplete parameters");
} catch (WebApplicationException wae) {
verifyIncompleteException(wae, "Action", "export", "storageDomain.id|name");
}
}
@Test
public void testMoveWithStorageDomainId() throws Exception {
StorageDomain storageDomain = new StorageDomain();
storageDomain.setId(GUIDS[2].toString());
doTestMove(storageDomain);
}
@Test
public void testMoveWithStorageDomainName() throws Exception {
setUpGetEntityExpectations("Storage: name=" + NAMES[2],
SearchType.StorageDomain,
getStorageDomain(2));
StorageDomain storageDomain = new StorageDomain();
storageDomain.setName(NAMES[2]);
doTestMove(storageDomain);
}
@Test
public void testIncompleteMove() throws Exception {
setUriInfo(setUpBasicUriExpectations());
try {
control.replay();
resource.move(new Action());
fail("expected WebApplicationException on incomplete parameters");
} catch (WebApplicationException wae) {
verifyIncompleteException(wae, "Action", "move", "storageDomain.id|name");
}
}
protected void doTestMove(StorageDomain storageDomain) throws Exception {
setUriInfo(setUpActionExpectations(VdcActionType.MoveVm,
MoveVmParameters.class,
new String[] { "ContainerId", "StorageDomainId" },
new Object[] { GUIDS[0], GUIDS[2] }));
Action action = new Action();
action.setStorageDomain(storageDomain);
verifyActionResponse(resource.move(action));
}
@Test
public void testStatisticalQuery() throws Exception {
org.ovirt.engine.core.common.businessentities.VM entity = setUpStatisticalExpectations();
@SuppressWarnings("unchecked")
BackendStatisticsResource<VM, org.ovirt.engine.core.common.businessentities.VM> statisticsResource =
(BackendStatisticsResource<VM, org.ovirt.engine.core.common.businessentities.VM>)resource.getStatisticsResource();
assertNotNull(statisticsResource);
verifyQuery(statisticsResource.getQuery(), entity);
}
protected org.ovirt.engine.core.common.businessentities.VM setUpStatisticalExpectations() throws Exception {
VmStatistics stats = control.createMock(VmStatistics.class);
org.ovirt.engine.core.common.businessentities.VM entity =
control.createMock(org.ovirt.engine.core.common.businessentities.VM.class);
setUpStatisticalEntityExpectations(entity, stats);
setUpGetEntityExpectations(1, false, entity);
control.replay();
return entity;
}
protected void verifyQuery(AbstractStatisticalQuery<VM, org.ovirt.engine.core.common.businessentities.VM> query,
org.ovirt.engine.core.common.businessentities.VM entity)
throws Exception {
assertEquals(VM.class, query.getParentType());
assertSame(entity, query.resolve(GUIDS[0]));
List<Statistic> statistics = query.getStatistics(entity);
verifyStatistics(statistics,
new String[] {"memory.installed", "memory.used", "cpu.current.guest",
"cpu.current.hypervisor", "cpu.current.total"},
new BigDecimal[] {asDec(10*Mb), asDec(2*Mb), asDec(30), asDec(40), asDec(70)});
Statistic adopted = query.adopt(new Statistic());
assertTrue(adopted.isSetVm());
assertEquals(GUIDS[0].toString(), adopted.getVm().getId());
}
protected void setUpGetHostIdExpectations(int idx) throws Exception {
VDS host = BackendHostsResourceTest.setUpEntityExpectations(control.createMock(VDS.class), idx);
setUpGetEntityExpectations(VdcQueryType.GetVdsByName,
GetVdsByNameParameters.class,
new String[] { "Name" },
new Object[] { NAMES[idx] },
host);
}
protected void setUpGetEntityExpectations(int times) throws Exception {
setUpGetEntityExpectations(times, false);
}
protected void setUpGetEntityExpectations(int times, boolean notFound) throws Exception {
setUpGetEntityExpectations(times, notFound, getEntity(0));
}
protected void setUpWindowsGetEntityExpectations(int times, boolean notFound) throws Exception {
setUpGetEntityExpectations(times,
notFound,
new org.ovirt.engine.core.common.businessentities.VM(){{setvm_guid(GUIDS[0]);setvm_os(VmOsType.WindowsXP);}});
}
protected void setUpGetEntityExpectations(int times, boolean notFound, org.ovirt.engine.core.common.businessentities.VM entity) throws Exception {
while (times-- > 0) {
setUpGetEntityExpectations(VdcQueryType.GetVmByVmId,
GetVmByVmIdParameters.class,
new String[] { "Id" },
new Object[] { GUIDS[0] },
notFound ? null : entity);
}
}
protected UriInfo setUpActionExpectations(VdcActionType task,
Class<? extends VdcActionParametersBase> clz,
String[] names,
Object[] values) {
return setUpActionExpectations(task, clz, names, values, true, true, null, null, true);
}
protected UriInfo setUpActionExpectations(VdcActionType task,
Class<? extends VdcActionParametersBase> clz,
String[] names,
Object[] values,
ArrayList<Guid> asyncTasks,
ArrayList<AsyncTaskStatus> asyncStatuses) {
String uri = "vms/" + GUIDS[0] + "/action";
return setUpActionExpectations(task, clz, names, values, true, true, null, asyncTasks, asyncStatuses, uri, true);
}
private void verifyActionResponse(Response r) throws Exception {
verifyActionResponse(r, "vms/" + GUIDS[0], false);
}
@Override
protected org.ovirt.engine.core.common.businessentities.VM getEntity(int index) {
return setUpEntityExpectations(
control.createMock(org.ovirt.engine.core.common.businessentities.VM.class),
control.createMock(VmStatistics.class),
index);
}
protected void verifyModelOnNewCluster(VM model, int index) {
assertNotNull(model.getCluster().getId());
assertEquals(GUIDS[2].toString(), model.getCluster().getId());
verifyModel(model, index);
}
protected void verifyModel(VM model, int index) {
super.verifyModel(model, index);
verifyModelSpecific(model, index);
}
protected storage_domains getStorageDomain(int idx) {
storage_domains dom = new storage_domains();
dom.setid(GUIDS[idx]);
return dom;
}
}