Maor Lipchuk has uploaded a new change for review. Change subject: core: Initialize entities in DB from OVF disk on attach ......................................................................
core: Initialize entities in DB from OVF disk on attach Adding VMs and Templates from the most updated OVF store disk into the unregistered entity table. The operation of this is being done when the user attach a Storage Domain to the DC. Change-Id: Ica68974916821ac1c9fbe6f43400170d19d716c9 Signed-off-by: Maor Lipchuk <[email protected]> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommand.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommandTest.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfParser.java 3 files changed, 141 insertions(+), 6 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/41/29041/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommand.java index 144cfcb..8342308 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommand.java @@ -1,6 +1,12 @@ package org.ovirt.engine.core.bll.storage; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute; import org.ovirt.engine.core.bll.context.CommandContext; @@ -10,16 +16,28 @@ import org.ovirt.engine.core.common.action.StoragePoolWithStoragesParameter; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; +import org.ovirt.engine.core.common.businessentities.Disk; +import org.ovirt.engine.core.common.businessentities.DiskImage; +import org.ovirt.engine.core.common.businessentities.OvfEntityData; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StorageDomainType; import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap; import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.queries.GetUnregisteredDisksQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.vdscommands.AttachStorageDomainVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.ImageHttpAccessVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; +import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.TransactionScopeOption; +import org.ovirt.engine.core.utils.JsonHelper; +import org.ovirt.engine.core.utils.archivers.tar.OutMemoryTar; +import org.ovirt.engine.core.utils.ovf.OvfInfoFileConstants; +import org.ovirt.engine.core.utils.ovf.OvfParser; import org.ovirt.engine.core.utils.transaction.TransactionMethod; @NonTransactiveCommandAttribute(forceCompensation = true) @@ -79,6 +97,7 @@ runVdsCommand(VDSCommandType.AttachStorageDomain, new AttachStorageDomainVDSCommandParameters(getParameters().getStoragePoolId(), getParameters().getStorageDomainId())); + final List<OvfEntityData> unregisteredEntitiesFromOvfDisk = getEntitiesFromStorageOvfDisk(); executeInNewTransaction(new TransactionMethod<Object>() { @Override public Object runInTransaction() { @@ -94,9 +113,20 @@ if (sdType == StorageDomainType.Data || sdType == StorageDomainType.Master) { updateStorageDomainFormat(getStorageDomain()); } + + // Update unregistered entities + for (OvfEntityData ovf : unregisteredEntitiesFromOvfDisk) { + getUnregisteredOVFDataDao().removeEntity(ovf.getEntityId(), + getParameters().getStorageDomainId()); + getUnregisteredOVFDataDao().saveOVFData(ovf); + log.infoFormat("Adding OVF data of entity id {0} and entity name {1}", + ovf.getEntityId(), + ovf.getEntityName()); + } return null; } }); + if (getParameters().getActivate()) { attemptToActivateDomain(); } @@ -104,7 +134,105 @@ } } } + } + protected List<OvfEntityData> getEntitiesFromStorageOvfDisk() { + List<OvfEntityData> ovfEntitiesFromTar = new ArrayList<>(); + + // Get all unregistered disks. + List<Disk> unregisteredDisks = getBackend().runInternalQuery(VdcQueryType.GetUnregisteredDisks, + new GetUnregisteredDisksQueryParameters(getParameters().getStorageDomainId(), + getVds().getStoragePoolId())).getReturnValue(); + + Pair<DiskImage, Long> ovfDiskAndSize = getLatestOVFDisk(unregisteredDisks); + DiskImage ovfDisk = ovfDiskAndSize.getFirst(); + if (ovfDisk != null) { + VDSReturnValue retrievedByteData = + runVdsCommand(VDSCommandType.RetrieveImageData, new ImageHttpAccessVDSCommandParameters(getVdsId(), + getParameters().getStoragePoolId(), + getParameters().getStorageDomainId(), + ovfDisk.getId(), + ovfDisk.getImage().getId(), + ovfDiskAndSize.getSecond())); + if (retrievedByteData.getSucceeded()) { + ovfEntitiesFromTar = + OutMemoryTar.unTar((byte[]) retrievedByteData.getReturnValue(), + getParameters().getStorageDomainId()); + } + } + return ovfEntitiesFromTar; + } + + /** + * Returns the best match for OVF disk from all the disks. If no OVF disk was found, it returns null for disk and + * size 0. If there are OVF disks, we first match the updated ones, and from them we retrieve the one which was last + * updated. + * + * @param disks + * - A list of disks + * @return A Pair which contains the best OVF disk to retrieve data from and its size. + */ + private Pair<DiskImage, Long> getLatestOVFDisk(List<Disk> disks) { + Date lastUpdate = new Date(); + boolean lastIsUpdated = false; + Long size = 0L; + Disk diskToGetOVF = null; + for (Disk disk : disks) { + boolean isDiskLastUpdated = false; + // Check which disks are of OVF_STORE + String diskDecription = ((DiskImage) disk).getDescription(); + if (diskDecription.contains(OvfInfoFileConstants.OvfStoreDescriptionLabel)) { + Map<String, Object> diskDescriptionMap = buildJson(diskDecription); + if (!isDomainExistsInDiskDescription(diskDescriptionMap, getParameters().getStorageDomainId())) { + break; + } + + boolean isUpdated = Boolean.valueOf(diskDescriptionMap.get(OvfInfoFileConstants.IsUpdated).toString()); + Date date = getDateFromDiskDescription(diskDescriptionMap); + // If last is updated is false, and the current disk was updated, then the current disk is what we are + // about to update from. + if (!lastIsUpdated && isUpdated) { + isDiskLastUpdated = true; + // If also the current disk was not updated, then check which disk has the latest update date. + } else if (!isUpdated && date.after(lastUpdate)) { + isDiskLastUpdated = true; + // If also the current disk was updated, then check which disk has the latest update date. + } else if (lastIsUpdated && isUpdated && date.after(lastUpdate)) { + isDiskLastUpdated = true; + } + + if (isDiskLastUpdated) { + lastIsUpdated = isUpdated; + lastUpdate = date; + diskToGetOVF = disk; + size = new Long(diskDescriptionMap.get(OvfInfoFileConstants.Size).toString()); + } + } + } + return new Pair<>((DiskImage)diskToGetOVF, size); + } + + private Date getDateFromDiskDescription(Map<String, Object> map) { + try { + return new SimpleDateFormat(OvfParser.formatStrFromDiskDescription).parse(map.get(OvfInfoFileConstants.LastUpdated) + .toString()); + } catch (java.text.ParseException e) { + log.errorFormat("LastUpdate Date could not be parsed from disk desscription"); + e.printStackTrace(); + return null; + } + } + + private boolean isDomainExistsInDiskDescription(Map<String, Object> map, Guid storageDomainId) { + return map.get(OvfInfoFileConstants.Domains).toString().contains(storageDomainId.toString()); + } + + private Map<String, Object> buildJson(String json) { + try { + return JsonHelper.jsonToMap(json); + } catch (IOException e) { + throw new RuntimeException("Exception while generating json containing ovf store info", e); + } } protected void attemptToActivateDomain() { diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommandTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommandTest.java index 04364f5..98a8aa5 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommandTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/storage/AttachStorageDomainToPoolCommandTest.java @@ -4,13 +4,14 @@ import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.List; import org.junit.ClassRule; import org.junit.Test; @@ -26,15 +27,16 @@ import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; +import org.ovirt.engine.core.common.businessentities.OvfEntityData; +import org.ovirt.engine.core.common.businessentities.StorageDomain; +import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; +import org.ovirt.engine.core.common.businessentities.StoragePool; +import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap; import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; -import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; -import org.ovirt.engine.core.common.businessentities.StorageDomain; -import org.ovirt.engine.core.common.businessentities.StoragePool; -import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMap; import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSParametersBase; @@ -107,6 +109,7 @@ when(vdsBrokerFrontend.RunVdsCommand(any(VDSCommandType.class), any(VDSParametersBase.class))) .thenReturn(returnValue); when(vdsDAO.get(any(Guid.class))).thenReturn(vds); + doReturn(getUnregisteredList()).when(cmd).getEntitiesFromStorageOvfDisk(); doAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { @@ -120,4 +123,8 @@ assertNotNull(map); assertEquals(StorageDomainStatus.Maintenance, map.getStatus()); } + + private List<OvfEntityData> getUnregisteredList() { + return new ArrayList<OvfEntityData>(); + } } diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfParser.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfParser.java index fb8dbbb..63d7e76 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfParser.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfParser.java @@ -17,9 +17,9 @@ import org.ovirt.engine.core.utils.log.LogFactory; public class OvfParser { - private static final String utcFallbackDateFormatStr = "yyyy.MM.dd HH:mm:ss"; private static final String utcDateFormatStr = "yyyy/MM/dd HH:mm:ss"; + public static final String formatStrFromDiskDescription = "EEE MMM d HH:mm:ss zzz yyyy"; protected XmlDocument _document; protected XmlNamespaceManager _xmlNS; -- To view, visit http://gerrit.ovirt.org/29041 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ica68974916821ac1c9fbe6f43400170d19d716c9 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Maor Lipchuk <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
