package org.ovirt.mobile.movirt.rest.client;
import android.content.Context;
import android.support.annotation.NonNull;
import org.androidannotations.annotations.AfterInject;
import org.androidannotations.annotations.App;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.RootContext;
import org.androidannotations.rest.spring.annotations.RestService;
import org.androidannotations.rest.spring.api.RestClientHeaders;
import org.androidannotations.rest.spring.api.RestClientRootUrl;
import org.androidannotations.rest.spring.api.RestClientSupport;
import org.ovirt.mobile.movirt.MoVirtApp;
import org.ovirt.mobile.movirt.auth.properties.AccountProperty;
import org.ovirt.mobile.movirt.auth.properties.manager.AccountPropertiesManager;
import org.ovirt.mobile.movirt.auth.properties.property.version.Version;
import org.ovirt.mobile.movirt.auth.properties.property.version.support.VersionSupport;
import org.ovirt.mobile.movirt.model.Cluster;
import org.ovirt.mobile.movirt.model.Console;
import org.ovirt.mobile.movirt.model.DataCenter;
import org.ovirt.mobile.movirt.model.Disk;
import org.ovirt.mobile.movirt.model.DiskAttachment;
import org.ovirt.mobile.movirt.model.Event;
import org.ovirt.mobile.movirt.model.Host;
import org.ovirt.mobile.movirt.model.Nic;
import org.ovirt.mobile.movirt.model.Snapshot;
import org.ovirt.mobile.movirt.model.StorageDomain;
import org.ovirt.mobile.movirt.model.Vm;
import org.ovirt.mobile.movirt.provider.OVirtContract;
import org.ovirt.mobile.movirt.rest.Request;
import org.ovirt.mobile.movirt.rest.RequestHandler;
import org.ovirt.mobile.movirt.rest.Response;
import org.ovirt.mobile.movirt.rest.RestEntityWrapper;
import org.ovirt.mobile.movirt.rest.RestEntityWrapperList;
import org.ovirt.mobile.movirt.rest.client.requestfactory.OvirtSimpleClientHttpRequestFactory;
import org.ovirt.mobile.movirt.rest.dto.Action;
import org.ovirt.mobile.movirt.rest.dto.Events;
import org.ovirt.mobile.movirt.rest.dto.SnapshotAction;
import org.ovirt.mobile.movirt.util.message.MessageHelper;
import org.ovirt.mobile.movirt.util.preferences.SettingsKey;
import org.ovirt.mobile.movirt.util.preferences.SharedPreferencesHelper;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.ovirt.mobile.movirt.rest.RestHelper.setAcceptEncodingHeaderAndFactory;
import static org.ovirt.mobile.movirt.rest.RestHelper.setFilterHeader;
import static org.ovirt.mobile.movirt.rest.RestHelper.setVersionHeader;
import static org.ovirt.mobile.movirt.rest.RestHelper.setupAuth;
@EBean(scope = EBean.Scope.Singleton)
public class OVirtClient {
private static final String TAG = OVirtClient.class.getSimpleName();
@RestService
OVirtRestClient restClient;
@Bean
RequestHandler requestHandler;
@Bean
OvirtSimpleClientHttpRequestFactory requestFactory;
@RootContext
Context context;
@Bean
AccountPropertiesManager propertiesManager;
@App
MoVirtApp app;
@Bean
SharedPreferencesHelper sharedPreferencesHelper;
@Bean
MessageHelper messageHelper;
private Version version;
@AfterInject
public void init() {
setAcceptEncodingHeaderAndFactory(restClient, requestFactory);
propertiesManager.notifyAndRegisterListener(new AccountProperty.VersionListener() {
@Override
public void onPropertyChange(Version newVersion) {
setVersionHeader(restClient, newVersion);
setupAuth(restClient, newVersion);
version = newVersion;
}
});
propertiesManager.notifyAndRegisterListener(new AccountProperty.ApiUrlListener() {
@Override
public void onPropertyChange(String apiUrl) {
restClient.setRootUrl(apiUrl);
}
});
propertiesManager.notifyAndRegisterListener(new AccountProperty.HasAdminPermissionsListener() {
@Override
public void onPropertyChange(Boolean hasAdminPermissions) {
setFilterHeader(restClient, hasAdminPermissions);
}
});
}
public void startVm(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.startVm(new Action(), vmId);
return null;
}
}, response);
}
public void stopVm(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.stopVm(new Action(), vmId);
return null;
}
}, response);
}
public void rebootVm(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.rebootVm(new Action(), vmId);
return null;
}
}, response);
}
public void migrateVmToHost(final String vmId, final String hostId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
Action action = version.isV3Api() ? new org.ovirt.mobile.movirt.rest.dto.v3.ActionMigrate(hostId) :
new org.ovirt.mobile.movirt.rest.dto.v4.ActionMigrate(hostId);
restClient.migrateVmToHost(action, vmId);
return null;
}
}, response);
}
public void migrateVmToDefaultHost(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.migrateVmToHost(new Action(), vmId);
return null;
}
}, response);
}
public void cancelMigration(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.cancelMigration(new Action(), vmId);
return null;
}
}, response);
}
@NonNull
public Request<Vm> getVmRequest(final String vmId) {
return new RestClientRequest<Vm>() {
@Override
public Vm fire() {
org.ovirt.mobile.movirt.rest.dto.Vm vm = version.isV3Api() ? restClient.getVmV3(vmId) : restClient.getVmV4(vmId);
return vm.toEntity();
}
};
}
public void getVm(final String vmId, Response<Vm> response) {
requestHandler.fireRestRequest(getVmRequest(vmId), response);
}
public void activateHost(final String hostId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.activateHost(new Action(), hostId);
return null;
}
}, response);
}
public void dectivateHost(final String hostId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.deactivateHost(new Action(), hostId);
return null;
}
}, response);
}
public void deleteSnapshot(final String vmId, final String snapshotId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.deleteSnapshot(vmId, snapshotId);
return null;
}
}, response);
}
public void restoreSnapshot(final SnapshotAction snapshotAction, final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
String snapshotId = snapshotAction.snapshot.id;
SnapshotAction restAction = new SnapshotAction(snapshotAction.restore_memory);
restClient.restoreSnapshot(restAction, vmId, snapshotId);
return null;
}
}, response);
}
public void previewSnapshot(final SnapshotAction snapshotAction, final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
if (version.isV3Api()) {
restClient.previewSnapshotV3(snapshotAction, vmId);
} else {
restClient.previewSnapshotV4(snapshotAction, vmId);
}
return null;
}
}, response);
}
public void createSnapshot(final org.ovirt.mobile.movirt.rest.dto.Snapshot snapshot, final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
restClient.createSnapshot(snapshot, vmId);
return null;
}
}, response);
}
public void commitSnapshot(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
if (version.isV3Api()) {
restClient.commitSnapshotV3(new Action(), vmId);
} else {
restClient.commitSnapshotV4(new Action(), vmId);
}
return null;
}
}, response);
}
public void undoSnapshot(final String vmId, Response<Void> response) {
requestHandler.fireRestRequest(new RestClientRequest<Void>() {
@Override
public Void fire() {
if (version.isV3Api()) {
restClient.undoSnapshotV3(new Action(), vmId);
} else {
restClient.undoSnapshotV4(new Action(), vmId);
}
return null;
}
}, response);
}
@NonNull
public Request<Host> getHostRequest(final String hostId) {
return new RestClientRequest<Host>() {
@Override
public Host fire() {
org.ovirt.mobile.movirt.rest.dto.Host wrapper = version.isV3Api() ?
restClient.getHostV3(hostId) : restClient.getHostV4(hostId);
return wrapper.toEntity();
}
};
}
public void getHost(final String hostId, Response<Host> response) {
requestHandler.fireRestRequest(getHostRequest(hostId), response);
}
@NonNull
public Request<StorageDomain> getStorageDomainRequest(final String storageDomainId) {
return new RestClientRequest<StorageDomain>() {
@Override
public StorageDomain fire() {
org.ovirt.mobile.movirt.rest.dto.StorageDomain wrapper = version.isV3Api() ?
restClient.getStorageDomainV3(storageDomainId) :
restClient.getStorageDomainV4(storageDomainId);
return wrapper.toEntity();
}
};
}
public void getStorageDomain(final String storageDomainId, Response<StorageDomain> response) {
requestHandler.fireRestRequest(getStorageDomainRequest(storageDomainId), response);
}
// currently not used
public Request<Disk> getDiskRequest(final String vmId, final String id) {
return getDiskRequest(vmId, null, id);
}
@NonNull
public Request<Disk> getDiskRequest(final String vmId, final String snapshotId, final String id) {
final boolean isSnapshotEmbedded = snapshotId != null;
return new RestClientRequest<Disk>() {
@Override
public Disk fire() {
org.ovirt.mobile.movirt.rest.dto.Disk wrapper;
Disk entity;
if (isSnapshotEmbedded) {
if (version.isV3Api()) {
wrapper = restClient.getDiskV3(vmId, snapshotId, id);
} else {
wrapper = restClient.getDiskV4(vmId, snapshotId, id);
}
entity = wrapper.toEntity();
setVmId(entity, vmId);
} else {
if (version.isV3Api()) {
wrapper = restClient.getDiskV3(vmId, id);
} else {
wrapper = restClient.getDiskV4(id);
}
entity = wrapper.toEntity();
}
return entity;
}
};
}
public Request<List<DiskAttachment>> getDisksAttachmentsRequest(final String vmId) {
return new RestClientRequest<List<DiskAttachment>>() {
@Override
public List<DiskAttachment> fire() {
VersionSupport.DISK_ATTACHMENTS.throwIfNotSupported(version);
return mapToEntities(restClient.getDisksAttachmentsV4(vmId));
}
};
}
public Request<List<Disk>> getDisksRequest(final String vmId, final String snapshotId) {
final boolean downloadAll = vmId == null;
final boolean isSnapshotEmbedded = snapshotId != null;
return new RestClientRequest<List<Disk>>() {
@Override
public List<Disk> fire() {
RestEntityWrapperList<? extends org.ovirt.mobile.movirt.rest.dto.Disk> wrappers;
List<Disk> entities;
if (downloadAll) {
if (version.isV3Api()) {
wrappers = restClient.getDisksV3();
} else {
wrappers = restClient.getDisksV4();
}
entities = mapToEntities(wrappers);
} else if (isSnapshotEmbedded) {
if (version.isV3Api()) {
wrappers = restClient.getDisksV3(vmId, snapshotId);
} else {
wrappers = restClient.getDisksV4(vmId, snapshotId);
}
entities = mapToEntities(wrappers);
setVmId(entities, vmId);
} else {
VersionSupport.VM_DISKS.throwIfNotSupported(version);
if (version.isV3Api()) {
wrappers = restClient.getDisksV3(vmId);
} else {
wrappers = restClient.getDisksV4(vmId);
}
entities = mapToEntities(wrappers);
}
return entities;
}
};
}
public void getClusters(Response<List<Cluster>> response) {
requestHandler.fireRestRequest(new RestClientRequest<List<Cluster>>() {
@Override
public List<Cluster> fire() {
if (version.isV3Api()) {
return mapToEntities(restClient.getClustersV3());
}
return mapToEntities(restClient.getClustersV4());
}
}, response);
}
public void getDataCenters(Response<List<DataCenter>> response) {
requestHandler.fireRestRequest(new RestClientRequest<List<DataCenter>>() {
@Override
public List<DataCenter> fire() {
if (version.isV3Api()) {
return mapToEntities(restClient.getDataCentersV3());
}
return mapToEntities(restClient.getDataCentersV4());
}
}, response);
}
public Request<Nic> getNicRequest(final String vmId, final String id) {
return getNicRequest(vmId, null, id);
}
@NonNull
public Request<Nic> getNicRequest(final String vmId, final String snapshotId, final String id) {
return new RestClientRequest<Nic>() {
@Override
public Nic fire() {
org.ovirt.mobile.movirt.rest.dto.Nic wrapper;
Nic entity;
if (snapshotId == null) {
if (version.isV3Api()) {
wrapper = restClient.getNicV3(vmId, id);
} else {
wrapper = restClient.getNicV4(vmId, id);
}
entity = wrapper.toEntity();
setVmId(entity, vmId);
} else {
if (version.isV3Api()) {
wrapper = restClient.getNicV3(vmId, snapshotId, id);
} else {
wrapper = restClient.getNicV4(vmId, snapshotId, id);
}
entity = wrapper.toEntity();
}
return entity;
}
};
}
public Request<List<Nic>> getNicsRequest(final String vmId) {
return getNicsRequest(vmId, null);
}
public Request<List<Nic>> getNicsRequest(final String vmId, final String snapshotId) {
return new RestClientRequest<List<Nic>>() {
@Override
public List<Nic> fire() {
RestEntityWrapperList<? extends org.ovirt.mobile.movirt.rest.dto.Nic> wrappers;
List<Nic> entities;
if (snapshotId == null) {
if (version.isV3Api()) {
wrappers = restClient.getNicsV3(vmId);
} else {
wrappers = restClient.getNicsV4(vmId);
}
entities = mapToEntities(wrappers);
setVmId(entities, vmId);
} else {
if (version.isV3Api()) {
wrappers = restClient.getNicsV3(vmId, snapshotId);
} else {
wrappers = restClient.getNicsV4(vmId, snapshotId);
}
entities = mapToEntities(wrappers);
}
return entities;
}
};
}
public Request<List<Host>> getHostsRequest() {
return new RestClientRequest<List<Host>>() {
@Override
public List<Host> fire() {
if (version.isV3Api()) {
return mapToEntities(restClient.getHostsV3());
}
return mapToEntities(restClient.getHostsV4());
}
};
}
public Request<List<Vm>> getVmsRequest() {
return new RestClientRequest<List<Vm>>() {
@Override
public List<Vm> fire() {
RestEntityWrapperList<? extends org.ovirt.mobile.movirt.rest.dto.Vm> wrappers;
if (propertiesManager.hasAdminPermissions()) {
int maxVms = sharedPreferencesHelper.getMaxVms();
String query = sharedPreferencesHelper.getStringPref(SettingsKey.VMS_SEARCH_QUERY);
if (StringUtils.isEmpty(query)) {
wrappers = version.isV3Api() ? restClient.getVmsV3(maxVms) :
restClient.getVmsV4(maxVms);
} else {
wrappers = version.isV3Api() ? restClient.getVmsV3(query, maxVms) :
restClient.getVmsV4(query, maxVms);
}
} else {
wrappers = version.isV3Api() ? restClient.getVmsV3(-1) :
restClient.getVmsV4(-1);
}
return mapToEntities(wrappers);
}
};
}
public Request<List<StorageDomain>> getStorageDomainsRequest() {
return new RestClientRequest<List<StorageDomain>>() {
@Override
public List<StorageDomain> fire() {
if (version.isV3Api()) {
return mapToEntities(restClient.getStorageDomainsV3());
}
return mapToEntities(restClient.getStorageDomainsV4());
}
};
}
public Request<List<Snapshot>> getSnapshotsRequest(final String vmId) {
return new RestClientRequest<List<Snapshot>>() {
@Override
public List<Snapshot> fire() {
RestEntityWrapperList<? extends org.ovirt.mobile.movirt.rest.dto.Snapshot> wrappers;
List<Snapshot> entities;
if (version.isV3Api()) {
wrappers = restClient.getSnapshotsV3(vmId);
} else {
wrappers = restClient.getSnapshotsV4(vmId);
}
entities = mapToEntities(wrappers);
setVmId(entities, vmId); // Active VM Snapshot doesn't include this
return entities;
}
};
}
public Request<Snapshot> getSnapshotRequest(final String vmId, final String snapshotId) {
return new RestClientRequest<Snapshot>() {
@Override
public Snapshot fire() {
org.ovirt.mobile.movirt.rest.dto.Snapshot wrapper;
Snapshot entity;
if (version.isV3Api()) {
wrapper = restClient.getSnapshotV3(vmId, snapshotId);
} else {
wrapper = restClient.getSnapshotV4(vmId, snapshotId);
}
entity = wrapper.toEntity();
setVmId(entity, vmId);
return entity;
}
};
}
public Request<List<Console>> getConsolesRequest(final String vmId) {
return new RestClientRequest<List<Console>>() {
@Override
public List<Console> fire() {
return mapToEntities(restClient.getConsoles(vmId));
}
};
}
public void getEventsSince(final int lastEventId, Response<List<Event>> response) {
requestHandler.fireRestRequest(new RestClientRequest<List<Event>>() {
@Override
public List<Event> fire() {
Events loadedEvents = null;
if (propertiesManager.hasAdminPermissions()) {
int maxEventsStored = sharedPreferencesHelper.getMaxEvents();
String query = sharedPreferencesHelper.getStringPref(SettingsKey.EVENTS_SEARCH_QUERY);
if (!"".equals(query)) {
loadedEvents = restClient.getEventsSince(Integer.toString(lastEventId), query, maxEventsStored);
} else {
loadedEvents = restClient.getEventsSince(Integer.toString(lastEventId), maxEventsStored);
}
} else {
loadedEvents = restClient.getEventsSince(Integer.toString(lastEventId), -1);
}
if (loadedEvents == null) {
return Collections.emptyList();
}
return mapToEntities(loadedEvents, new WrapPredicate<org.ovirt.mobile.movirt.rest.dto.Event>() {
@Override
public boolean toWrap(org.ovirt.mobile.movirt.rest.dto.Event entity) {
return entity.id > lastEventId;
}
});
}
}, response);
}
private <E, U extends RestEntityWrapper<E>> List<E> mapToEntities(RestEntityWrapperList<U> wrappersList) {
return mapToEntities(wrappersList, null);
}
private <E, U extends RestEntityWrapper<E>> List<E> mapToEntities(RestEntityWrapperList<U> wrappersList, WrapPredicate<U> predicate) {
if (wrappersList == null) {
return Collections.emptyList();
}
List<U> wrappers = wrappersList.getList();
if (wrappers == null) {
return Collections.emptyList();
}
List<E> entities = new ArrayList<>();
for (U rest : wrappers) {
try {
if (predicate == null || predicate.toWrap(rest)) {
entities.add(rest.toEntity());
}
} catch (Exception e) {
// showing only as a toast since this problem may persist and we don't want to flood the user with messages like this as dialogs...
messageHelper.showToast("Error parsing rest response, ignoring: " + rest.toString() + " error: " + e.getMessage());
}
}
return entities;
}
private <E extends OVirtContract.HasVm> void setVmId(E entity, String vmId) {
if (entity != null && !StringUtils.isEmpty(vmId)) {
entity.setVmId(vmId);
}
}
private <E extends OVirtContract.HasVm> void setVmId(List<E> entities, String vmId) {
if (entities != null && !StringUtils.isEmpty(vmId)) {
for (E entity : entities) {
entity.setVmId(vmId);
}
}
}
private interface WrapPredicate<E> {
boolean toWrap(E entity);
}
private abstract class RestClientRequest<T> implements Request<T> {
@Override
@SuppressWarnings("unchecked")
public <U extends RestClientRootUrl & RestClientHeaders & RestClientSupport> U getRestClient() {
return (U) restClient;
}
}
}