Yair Zaslavsky has uploaded a new change for review. Change subject: core: Supporting hard coded ldap servers per domain ......................................................................
core: Supporting hard coded ldap servers per domain Adding support for hard coded ldap server list per domain. If such a list is configured for a given domain, no DNS SRV lookup will be made to obtain the servers list. This patch also removes ordering the ldap servers by score, and uses the ordering algorithms instead. Change-Id: Ic0914f2f6d9432ecac0cebee3790eae902a1329a Bug-Url: https://bugzilla.redhat.com/894681 Signed-off-by: Yair Zaslavsky <yzasl...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/DirectorySearcher.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Domain.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/GetRootDSETask.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandler.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandlingResponse.java D backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/ScorableLDAPServer.java D backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Score.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/UsersDomainsCacheManagerService.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/dns/DnsSRVLocator.java 9 files changed, 138 insertions(+), 148 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/64/11064/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/DirectorySearcher.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/DirectorySearcher.java index 33725e7..abb2ccc 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/DirectorySearcher.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/DirectorySearcher.java @@ -6,6 +6,7 @@ import java.util.List; import org.apache.commons.lang.StringUtils; +import org.ovirt.engine.core.bll.adbroker.serverordering.LdapServersOrderingAlgorithmFactory; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; @@ -74,60 +75,67 @@ List<URI> ldapServerURIs = domain.getLdapServers(); if (log.isDebugEnabled()) { - log.debug("Ldap server list ordered by highest score: " + StringUtils.join(ldapServerURIs, ", ")); + log.debug("Ldap server list: " + StringUtils.join(ldapServerURIs, ", ")); } List<?> response = null; for (Iterator<URI> iterator = ldapServerURIs.iterator(); iterator.hasNext();) { URI ldapURI = iterator.next(); - if (log.isDebugEnabled()) { - log.debug("Using Ldap server " + ldapURI); - } - try { - setException(null); - GetRootDSETask getRootDSETask = new GetRootDSETask(this, domainName, ldapURI); - PrepareLdapConnectionTask prepareLdapConnectionTask = - new PrepareLdapConnectionTask(this, ldapCredentials, domainName, ldapURI); - getRootDSETask.call(); // TODO: Not really async Can throw exception - LdapQueryExecution queryExecution = - LdapQueryExecutionBuilderImpl.getInstance() - .build(getDomainObject(domainName).getLdapProviderType(), queryData); - if (queryExecution.getBaseDN() != null && !queryExecution.getBaseDN().isEmpty()) { - setExplicitBaseDN(queryExecution.getBaseDN()); - } - - log.debug("find() : LDAP filter = " + queryExecution.getFilter() + - ", baseDN = " + queryExecution.getBaseDN() + - ", explicitBaseDN = " + explicitBaseDN + ", domain = " + queryExecution.getDomain() ); - - LDAPTemplateWrapper ldapTemplate = prepareLdapConnectionTask.call(); - if (ldapTemplate == null) { - return Collections.emptyList(); - } - response = new DirectorySearchTask(ldapTemplate, queryExecution, resultCount).call(); - domain.scoreLdapServer(ldapURI, Score.HIGH); - return response; // No point in continuing to next LDAP server if we have success. - } catch (Exception exception) { - LdapSearchExceptionHandlingResponse handlingResponse = handler.handle(exception,ldapCredentials); - Exception translatedException = handlingResponse.getTranslatedException(); - setException(translatedException); - domain.scoreLdapServer(ldapURI, handlingResponse.getServerScore()); - log.errorFormat("Failed ldap search server {0} due to {1}. We {2} try the next server", - ldapURI, - LdapBrokerUtils.getFriendlyExceptionMessage(translatedException), - handlingResponse.isTryNextServer() ? "should" : "should not"); - log.debugFormat("Failed ldap search server {0} due to {1}. We {2} try the next server", - ldapURI, - translatedException, - handlingResponse.isTryNextServer() ? "should" : "should not"); - if (!handlingResponse.isTryNextServer()) { - return Collections.emptyList(); - } + response = findAndOrderServers(queryData,ldapURI,domainName,resultCount,ldapServerURIs); + if (response != null) { + break; } } + domain.setLdapServers(ldapServerURIs); return response; } + private List<?> findAndOrderServers(LdapQueryData queryData, URI ldapURI, String domainName, long resultCount, List<URI> modifiedLdapServersURIs) { + if (log.isDebugEnabled()) { + log.debug("Using Ldap server " + ldapURI); + } + try { + setException(null); + GetRootDSETask getRootDSETask = new GetRootDSETask(this, domainName, ldapURI); + PrepareLdapConnectionTask prepareLdapConnectionTask = + new PrepareLdapConnectionTask(this, ldapCredentials, domainName, ldapURI); + getRootDSETask.call(); // TODO: Not really async Can throw exception + LdapQueryExecution queryExecution = + LdapQueryExecutionBuilderImpl.getInstance() + .build(getDomainObject(domainName).getLdapProviderType(), queryData); + if (queryExecution.getBaseDN() != null && !queryExecution.getBaseDN().isEmpty()) { + setExplicitBaseDN(queryExecution.getBaseDN()); + } + + log.debug("find() : LDAP filter = " + queryExecution.getFilter() + + ", baseDN = " + queryExecution.getBaseDN() + + ", explicitBaseDN = " + explicitBaseDN + ", domain = " + queryExecution.getDomain() ); + + LDAPTemplateWrapper ldapTemplate = prepareLdapConnectionTask.call(); + if (ldapTemplate == null) { + return Collections.emptyList(); + } + return new DirectorySearchTask(ldapTemplate, queryExecution, resultCount).call(); + } catch (Exception exception) { + LdapSearchExceptionHandlingResponse handlingResponse = handler.handle(exception,ldapCredentials); + Exception translatedException = handlingResponse.getTranslatedException(); + setException(translatedException); + LdapServersOrderingAlgorithmFactory.getInstance().getOrderingAlgorithm(handlingResponse.getOrderingAlgorithm()).replaceLdapServerInList(ldapURI, modifiedLdapServersURIs); + log.errorFormat("Failed ldap search server {0} due to {1}. We {2} try the next server", + ldapURI, + LdapBrokerUtils.getFriendlyExceptionMessage(translatedException), + handlingResponse.isTryNextServer() ? "should" : "should not"); + log.debugFormat("Failed ldap search server {0} due to {1}. We {2} try the next server", + ldapURI, + translatedException, + handlingResponse.isTryNextServer() ? "should" : "should not"); + if (!handlingResponse.isTryNextServer()) { + return null; + } + } + return null; + } + public void setException(Exception ex) { this.ex = ex; } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Domain.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Domain.java index 5555844..63e9c1e 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Domain.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Domain.java @@ -2,11 +2,9 @@ import java.net.URI; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedList; import java.util.List; -import java.util.concurrent.locks.ReentrantLock; -import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.ovirt.engine.core.ldap.LdapProviderType; import org.ovirt.engine.core.utils.log.Log; @@ -16,15 +14,15 @@ private String name; // domain name private RootDSE rootDSE; // rootDSE for domain - private Map<URI, ScorableLDAPServer> ldapServers = new HashMap<URI, ScorableLDAPServer>(); // LDAP servers that match + private List<URI> ldapServers = new LinkedList<URI>(); // LDAP servers that match private LdapProviderType ldapProviderType; private LDAPSecurityAuthentication ldapSecurityAuthentication; private String userName; private String password; - private ReentrantLock lock = new ReentrantLock(); + private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // for this - private final static Log log = LogFactory.getLog(ScorableLDAPServer.class); + private final static Log log = LogFactory.getLog(Domain.class); public Domain(String domainName) { name = domainName; @@ -51,22 +49,24 @@ } public void setLdapServers(List<URI> ldapServersURIs) { - for (URI uri : ldapServersURIs) { - ldapServers.put(uri, new ScorableLDAPServer(uri)); + lock.writeLock().lock(); + try { + this.ldapServers = ldapServersURIs; + } finally { + lock.writeLock().unlock(); } } public List<URI> getLdapServers() { - List<ScorableLDAPServer> ldapServersCopy = new ArrayList<ScorableLDAPServer>(ldapServers.values()); - Collections.sort(ldapServersCopy); - - List<URI> servers = new ArrayList<URI>(); - for (ScorableLDAPServer server : ldapServersCopy) { - servers.add(server.getURI()); + lock.readLock().lock(); + try { + return new ArrayList<URI>(ldapServers); + } finally { + lock.readLock().unlock(); } - return servers; } + /* public void scoreLdapServer(URI ldapURI, Score score) { ScorableLDAPServer server = ldapServers.get(ldapURI); if (server != null) { @@ -76,12 +76,12 @@ } } } + */ public void addLDAPServer(URI uri) { - if (uri != null) { - ldapServers.put(uri, new ScorableLDAPServer(uri)); - } + ldapServers.add(uri); } + public LDAPSecurityAuthentication getLdapSecurityAuthentication() { return ldapSecurityAuthentication; @@ -107,7 +107,7 @@ this.password = password; } - public ReentrantLock getLock() { + public ReentrantReadWriteLock getLock() { return lock; } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/GetRootDSETask.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/GetRootDSETask.java index 32f1000..3f62d80 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/GetRootDSETask.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/GetRootDSETask.java @@ -54,7 +54,7 @@ // construct a rootDSE object and provide a baseDN that assumes // that all users will be under "cn=users" if (rootDSE == null) { - domainObject.getLock().lock(); + domainObject.getLock().writeLock().lock(); try { rootDSE = domainObject.getRootDSE(); if (rootDSE == null) { @@ -77,7 +77,7 @@ baseDNExist = true; } } finally { - domainObject.getLock().unlock(); + domainObject.getLock().writeLock().unlock(); } } else { baseDNExist = true; diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandler.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandler.java index 2986bd2..eb4f11c 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandler.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandler.java @@ -6,6 +6,7 @@ import javax.security.sasl.SaslException; import org.apache.commons.lang.exception.ExceptionUtils; +import org.ovirt.engine.core.bll.adbroker.serverordering.OrderingAlgorithmType; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; import org.ovirt.engine.core.utils.kerberos.AuthenticationResult; @@ -50,11 +51,11 @@ private void handleGeneralException(LdapSearchExceptionHandlingResponse response, Exception e) { response.setTranslatedException(e) .setTryNextServer(true) - .setServerScore(Score.LOW); + .setOrderingAlgorithm(OrderingAlgorithmType.PUT_LAST); } private void handleSaslException(LdapSearchExceptionHandlingResponse response, Throwable cause) { - response.setServerScore(Score.LOW) + response.setOrderingAlgorithm(OrderingAlgorithmType.PUT_LAST) .setTranslatedException(new AuthenticationResultException(AuthenticationResult.CONNECTION_ERROR, "General connection problem due to " + cause)) .setTryNextServer(true); @@ -62,7 +63,7 @@ private void handleOperationException(LdapSearchExceptionHandlingResponse response, Throwable throwable, LdapCredentials credentials) { - response.setServerScore(Score.HIGH) + response.setOrderingAlgorithm(OrderingAlgorithmType.NO_OP) .setTranslatedException(new AuthenticationResultException(AuthenticationResult.USER_ACCOUNT_DISABLED_OR_LOCKED, throwable)) .setTryNextServer(false); @@ -72,21 +73,21 @@ } private void handleInterruptException(LdapSearchExceptionHandlingResponse response, Throwable cause) { - response.setServerScore(Score.HIGH) + response.setOrderingAlgorithm(OrderingAlgorithmType.NO_OP) .setTranslatedException((Exception) cause) .setTryNextServer(false); } private void handleCommunicationException(LdapSearchExceptionHandlingResponse response, Throwable cause) { log.error("Error in communicating with LDAP server " + cause.getMessage()); - response.setServerScore(Score.LOW).setTryNextServer(true).setTranslatedException((Exception) cause); + response.setOrderingAlgorithm(OrderingAlgorithmType.PUT_LAST).setTryNextServer(true).setTranslatedException((Exception) cause); } private void handleAuthenticationException(LdapSearchExceptionHandlingResponse response) { log.error("Ldap authentication failed. Please check that the login name , password and path are correct. "); AuthenticationResultException ex = new AuthenticationResultException(AuthenticationResult.OTHER); - response.setServerScore(Score.HIGH) + response.setOrderingAlgorithm(OrderingAlgorithmType.NO_OP) .setTranslatedException(ex) .setTryNextServer(false); } @@ -98,10 +99,10 @@ case CONNECTION_ERROR: case CONNECTION_TIMED_OUT: case CLOCK_SKEW_TOO_GREAT: - response.setServerScore(Score.LOW).setTryNextServer(true); + response.setOrderingAlgorithm(OrderingAlgorithmType.PUT_LAST).setTryNextServer(true); break; default: - response.setServerScore(Score.HIGH).setTryNextServer(false); + response.setOrderingAlgorithm(OrderingAlgorithmType.NO_OP).setTryNextServer(false); break; } } @@ -111,7 +112,7 @@ .setTranslatedException( new AuthenticationResultException(AuthenticationResult.CONNECTION_TIMED_OUT, "Connection to to server has timed out.")) - .setServerScore(Score.LOW); + .setOrderingAlgorithm(OrderingAlgorithmType.PUT_LAST); } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandlingResponse.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandlingResponse.java index ed0c29e..027777b 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandlingResponse.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/LdapSearchExceptionHandlingResponse.java @@ -1,16 +1,14 @@ package org.ovirt.engine.core.bll.adbroker; +import org.ovirt.engine.core.bll.adbroker.serverordering.OrderingAlgorithmType; + public class LdapSearchExceptionHandlingResponse { private boolean tryNextServer; - private Score serverScore; private Exception translatedException; + private OrderingAlgorithmType orderingAlgorithm; public boolean isTryNextServer() { return tryNextServer; - } - - public Score getServerScore() { - return serverScore; } public Exception getTranslatedException() { @@ -22,13 +20,18 @@ return this; } - public LdapSearchExceptionHandlingResponse setServerScore(Score serverScore) { - this.serverScore = serverScore; - return this; - } public LdapSearchExceptionHandlingResponse setTranslatedException(Exception translatedException) { this.translatedException = translatedException; return this; } + + public OrderingAlgorithmType getOrderingAlgorithm() { + return orderingAlgorithm; + } + + public LdapSearchExceptionHandlingResponse setOrderingAlgorithm(OrderingAlgorithmType orderingAlgorithm) { + this.orderingAlgorithm = orderingAlgorithm; + return this; + } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/ScorableLDAPServer.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/ScorableLDAPServer.java deleted file mode 100644 index 924eabd..0000000 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/ScorableLDAPServer.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.ovirt.engine.core.bll.adbroker; - -import java.net.URI; - -public class ScorableLDAPServer implements LDAPServer, Comparable<ScorableLDAPServer> { - - final private URI uri; - private int score; - - public ScorableLDAPServer(URI uri) { - this.uri = uri; - } - - - /** - * Defensive copy of the URI. Prevents mutating the inner URI - */ - @Override - public URI getURI() { - return URI.create(uri.toString()); - } - - @Override - public int compareTo(ScorableLDAPServer o) { - return o.getScore() - getScore(); - } - - public void setScore(int score) { - this.score = score; - } - - public int getScore() { - return score; - } - -} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Score.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Score.java deleted file mode 100644 index 7f92c62..0000000 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/Score.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.ovirt.engine.core.bll.adbroker; - -public enum Score { - LOW(0), - HIGH(10); - - private Score(int val) { - this.val = val; - } - - final private int val; - - public int getValue() { - return val; - } - -} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/UsersDomainsCacheManagerService.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/UsersDomainsCacheManagerService.java index f99fd8b..7562bf9 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/UsersDomainsCacheManagerService.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/adbroker/UsersDomainsCacheManagerService.java @@ -2,6 +2,7 @@ import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -57,7 +58,7 @@ new HashMap<String, ConcurrentHashMap<String, UserDomainInfo>>(); private Map<String, ConcurrentHashMap<String, LdapGroup>> groupsPerDomain = new HashMap<String, ConcurrentHashMap<String, LdapGroup>>(); - private Map<String, URI> ldapServerPerDomain = new HashMap<String, URI>(); + private Map<String, List<URI>> ldapServerPerDomain = new HashMap<String, List<URI>>(); private final String DEFAULT_SECURITY_AUTHENTICATION_KEY = "default"; private Map<String, LDAPSecurityAuthentication> ldapSecurityAuthenticationPerDomain = new HashMap<String, LDAPSecurityAuthentication>(); @@ -81,8 +82,16 @@ URI ldapURI; try { - ldapURI = new URI("ldap://" + parts[1].trim() + ":" + ldapPort); - ldapServerPerDomain.put(domain, ldapURI); + String[] ldapServers = parts[1].trim().split(";"); + List<URI> uris = ldapServerPerDomain.get(domain); + if (uris == null) { + uris = new ArrayList<URI>(); + ldapServerPerDomain.put(domain,uris); + } + for (String ldapServer:ldapServers) { + ldapURI = new URI("ldap://" + ldapServer.trim() + ":" + ldapPort); + uris.add(ldapURI); + } } catch (URISyntaxException e) { log.errorFormat("Failed constructing LDAP server URL for domain {0}", domain); } @@ -212,10 +221,12 @@ private void obtainLDAPServersForDomain(Domain domain) { - URI ldapServerURI = ldapServerPerDomain.get(domain.getName()); + List<URI> ldapServers = ldapServerPerDomain.get(domain.getName()); - if (ldapServerURI != null) { - domain.addLDAPServer(ldapServerURI); + if (ldapServers != null) { + for (URI ldapServerURI:ldapServers) { + domain.addLDAPServer(ldapServerURI); + } return; } @@ -232,7 +243,7 @@ for (int counter = 0; counter < results.getNumOfValidAddresses(); counter++) { String address = results.getAddresses()[counter]; try { - URI ldapURI = locator.constructURI("LDAP", address); + URI ldapURI = locator.constructURI("LDAP", address,null); domain.addLDAPServer(ldapURI); } catch (URISyntaxException e) { log.errorFormat("Error in getting LDAP url based on srv record for address {0}", address); diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/dns/DnsSRVLocator.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/dns/DnsSRVLocator.java index 2b70af0..256ed5d 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/dns/DnsSRVLocator.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/dns/DnsSRVLocator.java @@ -5,9 +5,11 @@ import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Hashtable; import java.util.InputMismatchException; +import java.util.List; import java.util.Random; import java.util.Scanner; import java.util.regex.Pattern; @@ -333,14 +335,32 @@ } } - public URI constructURI(String protocol, String address) throws URISyntaxException { + public List<String> getServersList(DnsSRVResult result) { + List<String> results = new ArrayList<String>(); + if (result == null) { + return null; + } + for (int counter = 0 ; counter <result.getNumOfValidAddresses(); counter++) { + results.add(result.getAddresses()[counter]); + } + return results; + } + + public URI constructURI(String protocol, String address, String defaultLdapSeverPort) throws URISyntaxException { String[] parts = address.split("\\.:"); - if (parts.length != 2) { - throw new IllegalArgumentException("the address in SRV record should contain host and port"); + String hostname = address; + String port = defaultLdapSeverPort; + if (parts.length == 2) { + hostname = parts[0]; + port = parts[1]; + } else { + if (port == null) { + throw new IllegalArgumentException("the address in SRV record should contain host and port"); + } } StringBuilder uriSB = new StringBuilder(protocol); - uriSB.append("://").append(parts[0]).append(":").append(parts[1]); + uriSB.append("://").append(hostname).append(":").append(port); return new URI(uriSB.toString()); } -- To view, visit http://gerrit.ovirt.org/11064 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic0914f2f6d9432ecac0cebee3790eae902a1329a Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Yair Zaslavsky <yzasl...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches