Liron Ar has uploaded a new change for review. Change subject: core: Intrdoucing UploadStream capabillity ......................................................................
core: Intrdoucing UploadStream capabillity The following patch adds UploadStreamCommand/UploadStreamVDSCommand to allow streaming data to vdsm using HTTP. Opposed to regular vdsm verbs that usually have very short sync part, the whole upload needs to be executed in the sync part of the execution in order to stream the whole request body. This operations is a spm operation on the vdsm side, which means that we'll need to execute a spm command with a possibly long sync part (depends on the length of the passed stream) - which is a issue as currently each spm command executed by the engine takes an exclusive spm lock, executes it's short sync part (usually creates task) and return. Therefore, in this patch a support for executing multiple spm commands at the same time had to be added (we don't want to perform the whole upload under the exclusive spm lock). What was done in this patch with use of the LockManager - add a "VDS_EXECUTION" lock type to the and acquire it as shared when uploading stream and as exclusive when stopping the spm while not preventing other spm commands to run meanwhile. Another way to implement this is to add ReadWriteLock to IrsBrokerCommand, which i have implemented locally - according to the reviews i'll choose in which path to go. Currently there is no task created on vdsm side, so task create parts are commented out and will be deleted completly as soon as the vdsm patch will be merged with it's current implementation. Change-Id: I7af6e7b580e8844c1f0cd661d7f62ece688e31d3 Signed-off-by: Liron Aravot <lara...@redhat.com> --- A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UploadStreamCommand.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/bll/UploadStreamParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/constants/StorageConstants.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/UploadStreamVDSCommandParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java A backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/UploadStreamVDSCommand.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SpmStopVDSCommand.java 9 files changed, 403 insertions(+), 3 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/60/23460/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UploadStreamCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UploadStreamCommand.java new file mode 100644 index 0000000..323ff11 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UploadStreamCommand.java @@ -0,0 +1,113 @@ +package org.ovirt.engine.core.bll; + +import java.util.Collections; +import java.util.Map; + +import org.ovirt.engine.core.common.asynctasks.AsyncTaskType; +import org.ovirt.engine.core.common.businessentities.VDSStatus; +import org.ovirt.engine.core.common.businessentities.VdsDynamic; +import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.locks.LockingGroup; +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.common.vdscommands.UploadStreamVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.VDSCommandType; +import org.ovirt.engine.core.compat.Guid; + +@NonTransactiveCommandAttribute +@InternalCommandAttribute +public class UploadStreamCommand<T extends UploadStreamParameters> extends BaseImagesCommand<T> { + { + } + + public UploadStreamCommand(T parameters) { + super(parameters); + setStoragePoolId(getParameters().getStoragePoolId()); + } + + // @Override + // protected void insertAsyncTaskPlaceHolders() { + // persistAsyncTaskPlaceHolder(getParameters().getParentCommand()); + // } + + private Guid getPossibleSpmId() { + return getStoragePool().getspm_vds_id(); + } + + @Override + protected boolean canDoAction() { + VdsDynamic vdsDynamic = getVdsDynamicDao().get(getPossibleSpmId()); + if (vdsDynamic == null || vdsDynamic.getStatus() != VDSStatus.Up) { + addCanDoActionMessage(VdcBllMessages.VAR__HOST_STATUS__UP); + return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_VDS_STATUS_ILLEGAL); + } + + setStoragePool(null); + if (getStoragePool() == null) { + return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_POOL_NOT_EXIST); + } + + setVdsId(vdsDynamic.getId()); + + if (getStoragePool().getspm_vds_id() != getVdsId()) { + // add message that the host isn't the spm + return false; + } + + return true; + } + + @Override + protected void executeCommand() { + // Guid taskId = getAsyncTaskId(); + UploadStreamVDSCommandParameters vdsCommandParameters = + new UploadStreamVDSCommandParameters( + getVdsId(), + getParameters().getStoragePoolId(), + getParameters().getStorageDomainId(), + getParameters().getImageGroupID(), + getParameters().getImageId(), + getParameters().getInputStream(), + getParameters().getStreamLength()); + + runVdsCommand(VDSCommandType.UploadStream, vdsCommandParameters); + + // VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.UploadStream, vdsCommandParameters); + // + // // getParameters().setVdsmTaskIds(new java.util.ArrayList<Guid>()); + // // getParameters().getVdsmTaskIds().add( + // // createTask(taskId, + // // vdsReturnValue.getCreationInfo(), + // // getParameters().getParentCommand(), + // // VdcObjectType.Storage, + // // getParameters().getStorageDomainId(), + // // getParameters().getDestinationImageId())); + // // getReturnValue().getInternalVdsmTaskIdList().add(getParameters().getVdsmTaskIds().get(0)); + + setSucceeded(true); + } + +// @Override +// protected AsyncTaskType getTaskType() { +// return AsyncTaskType.copyImage; +// } + +// @Override +// protected void endSuccessfully() { +// setSucceeded(true); +// } +// +// @Override +// protected void endWithFailure() { +// setSucceeded(true); +// } + + @Override + protected Map<String, Pair<String, String>> getSharedLocks() { + if (getStoragePool() != null && getPossibleSpmId() != null) { + return Collections.singletonMap(getPossibleSpmId().toString(), + new Pair<>(LockingGroup.VDS_EXECUTION.toString(), + VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED.toString())); + } + return null; + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/bll/UploadStreamParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/bll/UploadStreamParameters.java new file mode 100644 index 0000000..8ac89bd --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/bll/UploadStreamParameters.java @@ -0,0 +1,50 @@ +package org.ovirt.engine.core.bll; + +import java.io.ByteArrayInputStream; + +import org.codehaus.jackson.annotate.JsonIgnore; +import org.ovirt.engine.core.common.action.ImagesContainterParametersBase; +import org.ovirt.engine.core.compat.Guid; + +public class UploadStreamParameters extends ImagesContainterParametersBase { + @JsonIgnore + ByteArrayInputStream inputStream; + + @JsonIgnore + Long streamLength; + + public UploadStreamParameters(Guid storagePoolId, + Guid storageDomainId, + Guid imageGroupId, + Guid imageId, + ByteArrayInputStream inputStream, + String streamInfo, + Long streamLength) { + super(imageId); + this.inputStream = inputStream; + this.streamLength = streamLength; + setStoragePoolId(storagePoolId); + setStorageDomainId(storageDomainId); + setImageGroupID(imageGroupId); + } + + public UploadStreamParameters() { + super(); + } + + public ByteArrayInputStream getInputStream() { + return inputStream; + } + + public void setInputStream(ByteArrayInputStream inputStream) { + this.inputStream = inputStream; + } + + public Long getStreamLength() { + return streamLength; + } + + public void setStreamLength(Long streamLength) { + this.streamLength = streamLength; + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java index 0f990b8..19c7b2f 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java @@ -303,7 +303,8 @@ AddInternalJob(1850, false, QuotaDependency.NONE), AddInternalStep(1851, false, QuotaDependency.NONE), - UpdateMomPolicy(1900, ActionGroup.MANIPUTLATE_HOST, false, QuotaDependency.NONE); + UpdateMomPolicy(1900, ActionGroup.MANIPUTLATE_HOST, false, QuotaDependency.NONE), + UploadStream(1901, QuotaDependency.NONE), private int intValue; private ActionGroup actionGroup; diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/constants/StorageConstants.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/constants/StorageConstants.java index 4a9065b..4d1c694 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/constants/StorageConstants.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/constants/StorageConstants.java @@ -2,4 +2,6 @@ public class StorageConstants { public static final int SIZE_IS_NOT_AVAILABLE = -1; + public static final int OVF_MAX_ITEMS_PER_SQL_STATEMENT = 100; + public static final int UPLOAD_SOCKET_TIMEOUT = 60; } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java index 9dee2c8..b6a5dbd 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java @@ -21,6 +21,7 @@ /** This group is used to lock template which is in export domain */ REMOTE_TEMPLATE, /** This group is used to lock VM which is in export domain */ - REMOTE_VM; + REMOTE_VM, + VDS_EXECUTION; } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/UploadStreamVDSCommandParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/UploadStreamVDSCommandParameters.java new file mode 100644 index 0000000..9721aa8 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/UploadStreamVDSCommandParameters.java @@ -0,0 +1,76 @@ +package org.ovirt.engine.core.common.vdscommands; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.ovirt.engine.core.compat.Guid; + +public class UploadStreamVDSCommandParameters extends VdsIdVDSCommandParametersBase { + InputStream inputStream; + Long streamLength; + Guid storagePoolId; + Guid storageDomainId; + Guid imageGroupId; + Guid imageId; + + public UploadStreamVDSCommandParameters(Guid vdsId, Guid storagePoolId, Guid storageDomainId, Guid imageGroupId, Guid imageId, ByteArrayInputStream inputStream, Long streamLength) { + super(vdsId); + this.inputStream = inputStream; + this.streamLength = streamLength; + this.storagePoolId = storagePoolId; + this.storageDomainId = storageDomainId; + this.imageGroupId = imageGroupId; + this.imageId = imageId; + } + + public UploadStreamVDSCommandParameters() { + } + + public InputStream getInputStream() { + return inputStream; + } + + public void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + + public Long getStreamLength() { + return streamLength; + } + + public void setStreamLength(Long streamLength) { + this.streamLength = streamLength; + } + + public Guid getStoragePoolId() { + return storagePoolId; + } + + public void setStoragePoolId(Guid storagePoolId) { + this.storagePoolId = storagePoolId; + } + + public Guid getStorageDomainId() { + return storageDomainId; + } + + public void setStorageDomainId(Guid storageDomainId) { + this.storageDomainId = storageDomainId; + } + + public Guid getImageGroupId() { + return imageGroupId; + } + + public void setImageGroupId(Guid imageGroupId) { + this.imageGroupId = imageGroupId; + } + + public Guid getImageId() { + return imageId; + } + + public void setImageId(Guid imageId) { + this.imageId = imageId; + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java index 27b7ab0..6b71813 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java @@ -101,6 +101,7 @@ SPMClearTask("org.ovirt.engine.core.vdsbroker.irsbroker"), SPMRevertTask("org.ovirt.engine.core.vdsbroker.irsbroker"), UpdateVM("org.ovirt.engine.core.vdsbroker.irsbroker"), + UploadStream("org.ovirt.engine.core.vdsbroker.irsbroker"), RemoveVM("org.ovirt.engine.core.vdsbroker.irsbroker"), SpmStopOnIrs("org.ovirt.engine.core.vdsbroker.irsbroker"), ResetISOPath("org.ovirt.engine.core.vdsbroker.vdsbroker"), diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/UploadStreamVDSCommand.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/UploadStreamVDSCommand.java new file mode 100644 index 0000000..3707fec --- /dev/null +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/irsbroker/UploadStreamVDSCommand.java @@ -0,0 +1,137 @@ +package org.ovirt.engine.core.vdsbroker.irsbroker; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.methods.InputStreamRequestEntity; +import org.apache.commons.httpclient.methods.PutMethod; +import org.codehaus.jackson.map.ObjectMapper; +import org.ovirt.engine.core.common.asynctasks.AsyncTaskCreationInfo; +import org.ovirt.engine.core.common.asynctasks.AsyncTaskType; +import org.ovirt.engine.core.common.businessentities.VdsStatic; +import org.ovirt.engine.core.common.config.Config; +import org.ovirt.engine.core.common.config.ConfigValues; +import org.ovirt.engine.core.common.constants.StorageConstants; +import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.locks.LockingGroup; +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.common.vdscommands.UploadStreamVDSCommandParameters; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.utils.lock.EngineLock; +import org.ovirt.engine.core.utils.log.Log; +import org.ovirt.engine.core.utils.log.LogFactory; +import org.ovirt.engine.core.vdsbroker.ResourceManager; +import org.ovirt.engine.core.vdsbroker.VdsManager; +import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusOnlyReturnForXmlRpc; +import org.ovirt.engine.core.vdsbroker.vdsbroker.VdsBrokerCommand; +import org.ovirt.engine.core.vdsbroker.vdsbroker.VdsServerWrapper; +import org.ovirt.engine.core.vdsbroker.xmlrpc.XmlRpcUtils; + +public class UploadStreamVDSCommand<P extends UploadStreamVDSCommandParameters> extends VdsBrokerCommand<P> { + + private static Log log = LogFactory.getLog(UploadStreamVDSCommand.class); + private EngineLock lock; + + public UploadStreamVDSCommand(P parameters) { + super(parameters); + } + + @Override + protected void executeVdsBrokerCommand() { + log.info("-- executeVdsBrokerCommand: "); + log.infoFormat("-- upload parameters:" + "\r\n" + + " dstSpUUID={0}" + "\r\n" + + " dstSdUUID={1}" + "\r\n" + + " dstImageGUID={2}" + "\r\n" + + " dstVolUUID={3}" + "\r\n", + getParameters().getStoragePoolId().toString(), + getParameters().getStorageDomainId().toString(), + getParameters().getImageGroupId().toString(), + getParameters().getImageId().toString()); + VdsManager manager = ResourceManager.getInstance().GetVdsManager(getParameters().getVdsId()); + HttpClient httpclient = ((VdsServerWrapper) manager.getVdsProxy()).getHttpClient(); + VdsStatic vdsStatic = + DbFacade.getInstance().getVdsStaticDao().get(manager.getVdsId()); + PutMethod putMethod = + new PutMethod(XmlRpcUtils.getConnectionUrl(vdsStatic.getHostName(), + vdsStatic.getPort(), + "", + Config.<Boolean> getValue(ConfigValues.EncryptHostCommunication)).getFirst()); + + putMethod.getParams().setParameter("http.socket.timeout", StorageConstants.UPLOAD_SOCKET_TIMEOUT); + + RuntimeException executionException = null; + try { + InputStreamRequestEntity inputStreamRequestEntity = null; + if (getParameters().getStreamLength() != null) { + inputStreamRequestEntity = + new InputStreamRequestEntity(getParameters().getInputStream(), + getParameters().getStreamLength()); + } else { + inputStreamRequestEntity = new InputStreamRequestEntity((getParameters().getInputStream())); + } + + putMethod.setRequestEntity(inputStreamRequestEntity); + putMethod.setRequestHeader("Content-Type", "application/octet-stream"); + if (getParameters().getStreamLength() != null) { + putMethod.setRequestHeader("Content-Length", getParameters().getStreamLength().toString()); + } + + putMethod.setRequestHeader("connection", "close"); + putMethod.setRequestHeader("X-Storage-Pool-Id", getParameters().getStoragePoolId().toString()); + putMethod.setRequestHeader("X-Storage-Domain-Id", getParameters().getStorageDomainId().toString()); + putMethod.setRequestHeader("X-Image-Id", getParameters().getImageGroupId().toString()); + putMethod.setRequestHeader("X-Volume-Id", getParameters().getImageId().toString()); + httpclient.executeMethod(putMethod); + + processResponseHeaderValue(putMethod, "Content-type", "application/json"); + status = new StatusOnlyReturnForXmlRpc( + new ObjectMapper().readValue(putMethod.getResponseBodyAsString(), HashMap.class)); + + String createdTaskId = processResponseHeaderValue(putMethod, "X-Task-Id", null); + + if (createdTaskId != null) { + Guid createdTask = Guid.createGuidFromString(createdTaskId); + getVDSReturnValue().setCreationInfo( + new AsyncTaskCreationInfo(createdTask, AsyncTaskType.copyImage, getParameters() + .getStoragePoolId())); + } + + getVDSReturnValue().setSucceeded(true); + } catch (Exception e) { + executionException = new RuntimeException(e); + } finally { + try { + putMethod.releaseConnection(); + } catch (Exception releaseException) { + log.error("failed when attempting to release connection", releaseException); + if (executionException != null) { + throw executionException; + } + throw releaseException; + } + } + + proceedProxyReturnValue(); + } + + private String processResponseHeaderValue(HttpMethodBase method, String headerName, String expectedValue) { + Header header = method.getResponseHeader(headerName); + if (header == null) { + throw new RuntimeException("UploadStreamVDSCommand - response was missing the following header: " + + headerName); + } + + if (expectedValue != null && !expectedValue.equals(header.getValue())) { + throw new RuntimeException("UploadStreamVDSCommand - response header value unexpected for header: " + + headerName); + } + + return header.getValue(); + } +} diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SpmStopVDSCommand.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SpmStopVDSCommand.java index 032e4c8..5cf83bd 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SpmStopVDSCommand.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SpmStopVDSCommand.java @@ -1,28 +1,45 @@ package org.ovirt.engine.core.vdsbroker.vdsbroker; +import java.util.Collections; import java.util.HashMap; +import java.util.Map; import org.ovirt.engine.core.common.businessentities.AsyncTaskStatus; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.errors.VDSError; import org.ovirt.engine.core.common.errors.VdcBllErrors; +import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.locks.LockingGroup; +import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.vdscommands.SpmStopVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.common.vdscommands.VdsIdVDSCommandParametersBase; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.utils.lock.EngineLock; +import org.ovirt.engine.core.utils.lock.LockManagerFactory; import org.ovirt.engine.core.vdsbroker.ResourceManager; public class SpmStopVDSCommand<P extends SpmStopVDSCommandParameters> extends VdsBrokerCommand<P> { + private EngineLock lock; + public SpmStopVDSCommand(P parameters) { super(parameters, DbFacade.getInstance().getVdsDao().get(parameters.getVdsId())); + } + + private EngineLock retrieveVdsExecutionLock() { + if (lock == null) { + Map<String, Pair<String, String>> exsluciveLock = Collections.singletonMap(getParameters().getVdsId().toString(), new Pair<>(LockingGroup.VDS_EXECUTION.toString(), VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED.toString())); + lock = new EngineLock(null, exsluciveLock); + } + return lock; } @Override protected void executeVdsBrokerCommand() { try { - if (canVdsBeReached()) { + if (canVdsBeReached() && LockManagerFactory.getLockManager().acquireLock(retrieveVdsExecutionLock()).getFirst()) { boolean performSpmStop = true; try { VDSReturnValue vdsReturnValue = ResourceManager @@ -72,6 +89,8 @@ .getStoragePoolId(), getParameters().getVdsId(), exp.toString()); getVDSReturnValue().setExceptionObject(exp); getVDSReturnValue().setSucceeded(false); + } finally { + LockManagerFactory.getLockManager().releaseLock(retrieveVdsExecutionLock()); } } -- To view, visit http://gerrit.ovirt.org/23460 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7af6e7b580e8844c1f0cd661d7f62ece688e31d3 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Liron Ar <lara...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches