package org.ovirt.engine.api.restapi.resource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import org.ovirt.engine.api.common.util.DetailHelper; import org.ovirt.engine.api.model.Disk; import org.ovirt.engine.api.model.Disks; import org.ovirt.engine.api.common.util.DetailHelper.Detail; import org.ovirt.engine.api.model.Action; import org.ovirt.engine.api.model.Nics; import org.ovirt.engine.api.model.Statistics; import org.ovirt.engine.api.model.Tags; import org.ovirt.engine.api.model.VM; import org.ovirt.engine.api.model.VMs; import org.ovirt.engine.api.resource.VmResource; import org.ovirt.engine.api.resource.VmsResource; import org.ovirt.engine.core.common.action.AddVmFromScratchParameters; import org.ovirt.engine.core.common.action.AddVmFromTemplateParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VmManagementParametersBase; import org.ovirt.engine.core.common.action.RemoveVmParameters; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.DiskImageBase; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSGroup; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.businessentities.VmTemplate; import org.ovirt.engine.core.common.businessentities.storage_domains; import org.ovirt.engine.core.common.interfaces.SearchType; import org.ovirt.engine.core.common.queries.GetAllDisksByVmIdParameters; import org.ovirt.engine.core.common.queries.GetStorageDomainsByVmTemplateIdQueryParameters; import org.ovirt.engine.core.common.queries.GetVmByVmIdParameters; import org.ovirt.engine.core.common.queries.GetVmTemplateParameters; import org.ovirt.engine.core.common.queries.GetVmTemplatesDisksParameters; import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.api.restapi.types.DiskMapper; public class BackendVmsResource extends AbstractBackendCollectionResource<VM, org.ovirt.engine.core.common.businessentities.VM> implements VmsResource { static final String[] SUB_COLLECTIONS = { "disks", "nics", "cdroms", "snapshots", "tags", "permissions", "statistics" }; public BackendVmsResource() { super(VM.class, org.ovirt.engine.core.common.businessentities.VM.class, SUB_COLLECTIONS); } @Override public VMs list() { return mapCollection(getBackendCollection(SearchType.VM)); } @Override @SingleEntityResource public VmResource getVmSubResource(String id) { return inject(new BackendVmResource(id, this)); } @Override public Response add(VM vm) { validateParameters(vm, "name", "template.id|name", "cluster.id|name"); Guid templateId = getTemplateId(vm); VmStatic staticVm = getMapper(VM.class, VmStatic.class).map(vm, getMapper(VmTemplate.class, VmStatic.class).map(lookupTemplate(templateId), null)); if (namedCluster(vm)) { staticVm.setvds_group_id(getClusterId(vm)); } //if the user set the host-name within placement-policy, rather than the host-id (legal) - //resolve the host's ID, because it will be needed down the line if (vm.isSetPlacementPolicy() && vm.getPlacementPolicy().isSetHost() && vm.getPlacementPolicy().getHost().isSetName() && !vm.getPlacementPolicy().getHost().isSetId()) { vm.getPlacementPolicy().getHost().setId(getHostId(vm.getPlacementPolicy().getHost().getName())); } Response response = null; Guid storageDomainId = ( vm.isSetStorageDomain() && vm.getStorageDomain().isSetId() ) ? asGuid(vm.getStorageDomain().getId()) : Guid.Empty; if (vm.isSetDisks() && vm.getDisks().isSetClone() && vm.getDisks().isClone()){ //disks are always cloned on the storage-domain, which contains the disk from which they are cloned. //therefore, even if user passed storage-domain, it is ignored in this context. response = cloneVmFromTemplate(staticVm, vm.getDisks(), templateId); } else if (templateId.equals(Guid.Empty)) { response = addVmFromScratch(staticVm, storageDomainId, vm.getDisks()); } else { response = addVm(staticVm, storageDomainId.equals(Guid.Empty) ? getTemplateStorageDomain(templateId) : storageDomainId); } return response; } private String getHostId(String hostName) { return getEntity(VDS.class, SearchType.VDS, "Hosts: name=" + hostName).getvds_id().toString(); } private Response cloneVmFromTemplate(VmStatic staticVm, Disks disks, Guid templateId) { return performCreation(VdcActionType.AddVmFromTemplate, new AddVmFromTemplateParameters(staticVm, getDisksToClone(disks, templateId), getTemplateStorageDomain(templateId)), new QueryIdResolver(VdcQueryType.GetVmByVmId, GetVmByVmIdParameters.class)); } private HashMap<String, DiskImageBase> getDisksToClone(Disks disks, Guid templateId) { HashMap<String, DiskImageBase> disksMap = new HashMap<String, DiskImageBase>(); if (disks.isSetDisks() && disks.getDisks().size() > 0){ HashMap<Guid, DiskImage> templatesDisksMap = getTemplateDisks(templateId); for(Disk disk : disks.getDisks()){ DiskImage templateDisk = templatesDisksMap.get(Guid.createGuidFromString(disk.getId())); if( templateDisk != null ){ disksMap.put(templateDisk.getinternal_drive_mapping(), map(disk, templateDisk)); } else { throw new WebApplicationException(Response.Status.NOT_FOUND); } } } return disksMap; } @SuppressWarnings("unchecked") private HashMap<Guid, DiskImage> getTemplateDisks(Guid templateId) { HashMap<Guid, DiskImage> templatesDisksMap = new HashMap<Guid, DiskImage>(); for(DiskImage di : (List<DiskImage>)getEntity(List.class, VdcQueryType.GetVmTemplatesDisks, new GetVmTemplatesDisksParameters(templateId), "Disks")){ templatesDisksMap.put(di.getId(), di); } return templatesDisksMap; } private DiskImage map(Disk entity, DiskImage template) { return getMapper(Disk.class, DiskImage.class).map(entity, template); } protected Response addVm(VmStatic staticVm, Guid storageDomainId) { VmManagementParametersBase params = new VmManagementParametersBase(staticVm); params.setStorageDomainId(storageDomainId); return performCreation(VdcActionType.AddVm, params, new QueryIdResolver(VdcQueryType.GetVmByVmId, GetVmByVmIdParameters.class)); } protected Response addVmFromScratch(VmStatic staticVm, Guid storageDomainId, Disks disks) { AddVmFromScratchParameters params = new AddVmFromScratchParameters(staticVm, mapDisks(disks), Guid.Empty); params.setStorageDomainId(storageDomainId); return performCreation(VdcActionType.AddVmFromScratch, params, new QueryIdResolver(VdcQueryType.GetVmByVmId, GetVmByVmIdParameters.class)); } private ArrayList<DiskImageBase> mapDisks(Disks disks) { ArrayList<DiskImageBase> diskImages = null; if (disks!=null && disks.isSetDisks()) { diskImages = new ArrayList<DiskImageBase>(); for (Disk disk : disks.getDisks()) { DiskImage diskImage = DiskMapper.map(disk, null); diskImages.add(diskImage); } } return diskImages; } protected VM addInlineDetails(Set<Detail> details, VM vm) { if (details.contains(Detail.DISKS)) { addInlineDisks(vm); } if (details.contains(Detail.NICS)) { addInlineNics(vm); } if (details.contains(Detail.TAGS)) { addInlineTags(vm); } return vm; } private void addInlineStatistics(VM vm) { EntityIdResolver resolver = new QueryIdResolver(VdcQueryType.GetVmByVmId, GetVmByVmIdParameters.class); VmStatisticalQuery query = new VmStatisticalQuery(resolver, newModel(vm.getId())); BackendStatisticsResource<VM, org.ovirt.engine.core.common.businessentities.VM> statisticsResource = inject(new BackendStatisticsResource<VM, org.ovirt.engine.core.common.businessentities.VM>(entityType, Guid.createGuidFromString(vm.getId()), query)); Statistics statistics = statisticsResource.list(); vm.setStatistics(statistics); } private void addInlineTags(VM vm) { BackendVmTagsResource tagsResource = inject(new BackendVmTagsResource(vm.getId())); Tags tags = tagsResource.list(); vm.setTags(tags); } private void addInlineNics(VM vm) { BackendVmNicsResource nicsResource = inject(new BackendVmNicsResource(asGuid(vm.getId()))); Nics nics = nicsResource.list(); vm.setNics(nics); } private void addInlineDisks(VM vm) { BackendDisksResource disksResource = inject(new BackendDisksResource(Guid.createGuidFromString(vm.getId()), VdcQueryType.GetAllDisksByVmId, new GetAllDisksByVmIdParameters(Guid.createGuidFromString(vm.getId())))); Disks disks = disksResource.list(); vm.setDisks(disks); } @Override public Response performRemove(String id) { return performAction(VdcActionType.RemoveVm, new RemoveVmParameters(asGuid(id), false)); } @Override public Response remove(String id, Action action) { getEntity(id); return performAction(VdcActionType.RemoveVm, new RemoveVmParameters(asGuid(id), action != null && action.isSetForce() ? action.isForce() : false)); } protected VMs mapCollection(List<org.ovirt.engine.core.common.businessentities.VM> entities) { VMs collection = new VMs(); for (org.ovirt.engine.core.common.businessentities.VM entity : entities) { collection.getVMs().add(addLinks(populate(map(entity), entity))); } return collection; } protected Guid getTemplateStorageDomain(Guid templateId) { Guid domainId = Guid.Empty; try { VdcQueryReturnValue queryReturn = backend.RunQuery( VdcQueryType.GetStorageDomainsByVmTemplateId, sessionize(new GetStorageDomainsByVmTemplateIdQueryParameters(templateId))); if (queryReturn.getSucceeded()) { storage_domains domain = (asCollection(storage_domains.class, queryReturn.getReturnValue())).get(0); if (domain != null) { domainId = domain.getid(); } } } catch (Exception e) { // best effort semantics } return domainId; } protected boolean templated(VM vm) { return vm.isSetTemplate() && (vm.getTemplate().isSetId() || vm.getTemplate().isSetName()); } protected Guid getTemplateId(VM vm) { return vm.getTemplate().isSetId() ? asGuid(vm.getTemplate().getId()) : getEntity( VmTemplate.class, SearchType.VmTemplate, "Template: name=" + vm.getTemplate().getName()).getId(); } public VmTemplate lookupTemplate(Guid id) { return getEntity(VmTemplate.class, VdcQueryType.GetVmTemplate, new GetVmTemplateParameters(id), "GetVmTemplate"); } protected boolean namedCluster(VM vm) { return vm.isSetCluster() && vm.getCluster().isSetName() && !vm.getCluster().isSetId(); } protected Guid getClusterId(VM vm) { return getEntity(VDSGroup.class, SearchType.Cluster, "Cluster: name=" + vm.getCluster().getName()).getID(); } @Override protected VM populate(VM model, org.ovirt.engine.core.common.businessentities.VM entity) { Set<Detail> details = DetailHelper.getDetails(getHttpHeaders()); model = addInlineDetails(details, model); if (details.contains(Detail.STATISTICS)) { addInlineStatistics(model); } return model; } }