package org.ovirt.mobile.movirt.ui.dashboard.general;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.content.Loader;
import android.support.v4.util.Pair;
import android.widget.TextView;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.ViewById;
import org.ovirt.mobile.movirt.R;
import org.ovirt.mobile.movirt.facade.HostFacade;
import org.ovirt.mobile.movirt.facade.VmFacade;
import org.ovirt.mobile.movirt.model.Host;
import org.ovirt.mobile.movirt.model.StorageDomain;
import org.ovirt.mobile.movirt.model.Vm;
import org.ovirt.mobile.movirt.model.mapping.EntityMapper;
import org.ovirt.mobile.movirt.provider.OVirtContract;
import org.ovirt.mobile.movirt.provider.ProviderFacade;
import org.ovirt.mobile.movirt.provider.SortOrder;
import org.ovirt.mobile.movirt.ui.MainActivityFragments;
import org.ovirt.mobile.movirt.ui.dashboard.PercentageCircleView;
import org.ovirt.mobile.movirt.ui.dashboard.general.resources.OverCommitResource;
import org.ovirt.mobile.movirt.ui.dashboard.general.resources.UtilizationResource;
import org.ovirt.mobile.movirt.util.usage.Cores;
import org.ovirt.mobile.movirt.util.usage.MemorySize;
import java.util.List;
import static org.ovirt.mobile.movirt.provider.OVirtContract.SnapshotEmbeddableEntity.SNAPSHOT_ID;
@EFragment(R.layout.fragment_dashboard_physical_general)
public class DashboardPhysicalGeneralFragment extends DashboardGeneralFragment {
private static final String TAG = DashboardPhysicalGeneralFragment.class.getSimpleName();
private static final int HOST_LOADER = 1;
private static final int STORAGE_DOMAIN_LOADER = 2;
private static final int VM_LOADER = 3;
@ViewById
TextView overCommitCpuPercentageCircle;
@ViewById
TextView overCommitMemoryPercentageCircle;
@Bean
ProviderFacade provider;
@Bean
HostFacade hostFacade;
@Bean
VmFacade vmFacade;
private UtilizationResource cpuResource;
private OverCommitResource cpuOverCommit = new OverCommitResource();
private UtilizationResource memoryResource;
private OverCommitResource memoryOverCommit = new OverCommitResource();
private UtilizationResource storageResource;
@AfterViews
void init() {
initLoaders();
}
@Override
protected int[] getLoaders() {
return new int[]{VM_LOADER, HOST_LOADER, STORAGE_DOMAIN_LOADER};
}
@ViewById
public void summaryMemoryPercentageCircle(TextView summaryMemoryPercentageCircle) {
super.summaryMemoryPercentageCircle = summaryMemoryPercentageCircle;
}
@ViewById
public void summaryCpuPercentageCircle(TextView summaryCpuPercentageCircle) {
super.summaryCpuPercentageCircle = summaryCpuPercentageCircle;
}
@ViewById
public void summaryStoragePercentageCircle(TextView summaryStoragePercentageCircle) {
super.summaryStoragePercentageCircle = summaryStoragePercentageCircle;
}
@ViewById
public void cpuPercentageCircle(PercentageCircleView cpuPercentageCircle) {
super.cpuPercentageCircle = cpuPercentageCircle;
}
@ViewById
public void memoryPercentageCircle(PercentageCircleView memoryPercentageCircle) {
super.memoryPercentageCircle = memoryPercentageCircle;
}
@ViewById
public void storagePercentageCircle(PercentageCircleView storagePercentageCircle) {
super.storagePercentageCircle = storagePercentageCircle;
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
Loader<Cursor> loader = null;
switch (id) {
case HOST_LOADER:
loader = provider.query(Host.class).asLoader();
break;
case STORAGE_DOMAIN_LOADER:
loader = provider.query(StorageDomain.class).where(StorageDomain.STATUS, StorageDomain.Status.ACTIVE.toString())
.where(StorageDomain.TYPE, StorageDomain.Type.DATA.toString()).asLoader();
break;
case VM_LOADER:
loader = provider.query(Vm.class).empty(SNAPSHOT_ID).asLoader();
break;
default:
break;
}
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
switch (loader.getId()) {
case HOST_LOADER:
List<Host> hosts = hostFacade.mapAllFromCursor(data);
processHostCpu(hosts);
processHostMemory(hosts);
renderCpuPercentageCircle();
renderMemoryPercentageCircle();
break;
case STORAGE_DOMAIN_LOADER:
List<StorageDomain> storageDomainList = EntityMapper.forEntity(StorageDomain.class).listFromCursor(data);
storageResource = getStorageDomainUtilization(storageDomainList);
renderStoragePercentageCircle();
break;
case VM_LOADER:
List<Vm> vms = vmFacade.mapAllFromCursor(data);
processVmCpuAndMemory(vms);
renderCpuPercentageCircle();
renderMemoryPercentageCircle();
break;
default:
break;
}
}
private void processVmCpuAndMemory(List<Vm> vms) {
Cores allVmCores = new Cores();
Cores upVmCores = new Cores();
MemorySize allVmMemory = new MemorySize();
MemorySize upVmMemory = new MemorySize();
for (Vm vm : vms) {
if (vm.getStatus() == Vm.Status.UP) {
upVmCores.addValue(vm);
upVmMemory.addValue(vm.getMemorySize());
}
allVmCores.addValue(vm);
allVmMemory.addValue(vm.getMemorySize());
}
cpuOverCommit.setVirtualTotal(allVmCores);
cpuOverCommit.setVirtualUsed(upVmCores);
memoryOverCommit.setVirtualTotal(allVmMemory);
memoryOverCommit.setVirtualUsed(upVmMemory);
}
private void processHostMemory(List<Host> hosts) {
memoryResource = getMemoryUtilization(hosts);
memoryOverCommit.setPhysicalTotal(memoryResource.getTotal());
}
private void processHostCpu(List<Host> hosts) {
Pair<UtilizationResource, Cores> utilization = getCpuUtilization(hosts);
cpuResource = utilization.first;
cpuOverCommit.setPhysicalTotal(utilization.second);
}
private UtilizationResource getStorageDomainUtilization(List<StorageDomain> domainList) {
MemorySize available = new MemorySize();
MemorySize used = new MemorySize();
MemorySize total;
for (StorageDomain entity : domainList) {
available.addValue(entity.getAvailableSize());
used.addValue(entity.getUsedSize());
}
total = new MemorySize(available.getValue() + used.getValue());
return new UtilizationResource(used, total, available);
}
private void renderCpuPercentageCircle() {
StartActivityAction cpuAction = new StartActivityAction(MainActivityFragments.HOSTS, OVirtContract.Vm.CPU_USAGE, SortOrder.DESCENDING);
super.renderCpuPercentageCircle(cpuResource, cpuAction);
renderOverCommit(overCommitCpuPercentageCircle, cpuOverCommit);
}
private void renderMemoryPercentageCircle() {
StartActivityAction memoryAction = new StartActivityAction(MainActivityFragments.HOSTS, OVirtContract.Vm.MEMORY_USAGE, SortOrder.DESCENDING);
super.renderMemoryPercentageCircle(memoryResource, memoryAction);
renderOverCommit(overCommitMemoryPercentageCircle, memoryOverCommit);
}
private void renderStoragePercentageCircle() {
super.renderStoragePercentageCircle(storageResource, new StartActivityAction(MainActivityFragments.STORAGE_DOMAIN,
OVirtContract.StorageDomain.STATUS, SortOrder.ASCENDING));
// No feasible way to get meaningful data from REST api to render over commit
}
private void renderOverCommit(TextView textView, OverCommitResource resource) {
if (resource != null && resource.isInitialized()) {
textView.setText(getString(R.string.over_commit_allocated, resource.getOvercommit(), resource.getAllocated()));
}
}
}