Piotr Kliczewski has uploaded a new change for review. Change subject: core: protocol fall back for older vdsms ......................................................................
core: protocol fall back for older vdsms When we try to install new host which only supports xmlrpc and we have cluster with compatibility level set to 3.5+ the code will fail. Solution for this issue is attempting to connect by using jsonrpc and if it fails falling back to xmlrpc. Bug-Url: https://bugzilla.redhat.com/1149655 Change-Id: Ie6f48bec60b520c089f326f8c5e79aec288ff3d6 Signed-off-by: pkliczewski <piotr.kliczew...@gmail.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/InstallVdsInternalCommand.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/transport/ProtocolDetector.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/FutureVDSCommandType.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/TimeBoundPollVDSCommandParameters.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/FutureMap.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java A backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/TimeBoundPollVDSCommand.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java 9 files changed, 211 insertions(+), 3 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/98/34098/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/InstallVdsInternalCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/InstallVdsInternalCommand.java index 7b4a58e..eeb07be 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/InstallVdsInternalCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/InstallVdsInternalCommand.java @@ -6,6 +6,7 @@ import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.network.NetworkConfigurator; +import org.ovirt.engine.core.bll.transport.ProtocolDetector; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.FeatureSupported; import org.ovirt.engine.core.common.action.InstallVdsParameters; @@ -14,7 +15,9 @@ import org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties; import org.ovirt.engine.core.common.businessentities.Provider; import org.ovirt.engine.core.common.businessentities.ProviderType; +import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; +import org.ovirt.engine.core.common.businessentities.VdsProtocol; import org.ovirt.engine.core.common.errors.VdcBllMessages; import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.utils.Pair; @@ -160,6 +163,19 @@ RunSleepOnReboot(getStatusOnReboot()); break; case Complete: + if (checkProtocolTofallback(getVds())) { + // we need to check whether we are connecting to vdsm which supports xmlrpc only + ProtocolDetector detector = new ProtocolDetector(getVds()); + if (!detector.attemptConnection()) { + detector.stopConnection(); + if (detector.attemptFallbackProtocol()) { + detector.setFallbackProtocol(); + } else { + detector.stopConnection(); + throw new VdsInstallException(VDSStatus.InstallFailed, "Host not reachable"); + } + } + } if (!configureNetworkUsingHostDeploy) { configureManagementNetwork(); } @@ -184,6 +200,10 @@ } } + private boolean checkProtocolTofallback(VDS vds) { + return VdsProtocol.STOMP.equals(vds.getProtocol()); + } + private void configureManagementNetwork() { final NetworkConfigurator networkConfigurator = new NetworkConfigurator(getVds(), getContext()); if (!networkConfigurator.awaitVdsmResponse()) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/transport/ProtocolDetector.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/transport/ProtocolDetector.java new file mode 100644 index 0000000..d24a1be --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/transport/ProtocolDetector.java @@ -0,0 +1,89 @@ +package org.ovirt.engine.core.bll.transport; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.ovirt.engine.core.bll.Backend; +import org.ovirt.engine.core.common.businessentities.VDS; +import org.ovirt.engine.core.common.businessentities.VdsProtocol; +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.interfaces.FutureVDSCall; +import org.ovirt.engine.core.common.vdscommands.FutureVDSCommandType; +import org.ovirt.engine.core.common.vdscommands.TimeBoundPollVDSCommandParameters; +import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.utils.transaction.TransactionMethod; +import org.ovirt.engine.core.utils.transaction.TransactionSupport; +import org.ovirt.engine.core.vdsbroker.ResourceManager; + +/** + * We need to detect whether vdsm supports jsonrpc or only xmlrpc. It is confusing to users + * when they have cluster 3.5+ and connect to vdsm <3.5 which supports only xmlrpc. + * In order to present version information in such situation we need fallback to xmlrpc. + * + */ +public class ProtocolDetector { + + private VDS vds; + + public ProtocolDetector(VDS vds) { + this.vds = vds; + } + + /** + * Attempts to connect to vdsm using a proxy from {@code VdsManager} for a host. + * + * @return <code>true</code> if connected or <code>false</code> if connection failed. + */ + public boolean attemptConnection() { + try { + long timeout = Config.<Integer> getValue(ConfigValues.SetupNetworksPollingTimeout); + FutureVDSCall<VDSReturnValue> task = + Backend.getInstance().getResourceManager().runFutureVdsCommand(FutureVDSCommandType.TimeBoundPoll, + new TimeBoundPollVDSCommandParameters(vds.getId(), timeout, TimeUnit.SECONDS)); + VDSReturnValue returnValue = + task.get(timeout, TimeUnit.SECONDS); + + if (returnValue.getSucceeded()) { + return true; + } + } catch (TimeoutException ignored) { + } + return false; + } + + /** + * Stops {@code VdsManager} for a host. + */ + public void stopConnection() { + ResourceManager.getInstance().RemoveVds(this.vds.getId()); + } + + /** + * Fall back the protocol and attempts the connection {@link ProtocolDetector#attemptConnection()}. + * + * @return <code>true</code> if connected or <code>false</code> if connection failed. + */ + public boolean attemptFallbackProtocol() { + vds.setProtocol(VdsProtocol.XML); + ResourceManager.getInstance().AddVds(vds, false); + return attemptConnection(); + } + + /** + * Updates DB with fall back protocol (xmlrpc). + */ + public void setFallbackProtocol() { + final VdsStatic vdsStatic = this.vds.getStaticData(); + vdsStatic.setProtocol(VdsProtocol.XML); + TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { + @Override + public Void runInTransaction() { + DbFacade.getInstance().getVdsStaticDao().update(vdsStatic); + return null; + } + }); + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/FutureVDSCommandType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/FutureVDSCommandType.java index e90c07d..59c74fa 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/FutureVDSCommandType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/FutureVDSCommandType.java @@ -2,7 +2,8 @@ public enum FutureVDSCommandType { SetupNetworks, - Poll; + Poll, + TimeBoundPoll; private static final String DEFAULT_PACKAGE = "org.ovirt.engine.core.vdsbroker.vdsbroker"; String packageName; diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/TimeBoundPollVDSCommandParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/TimeBoundPollVDSCommandParameters.java new file mode 100644 index 0000000..5f7307e --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/TimeBoundPollVDSCommandParameters.java @@ -0,0 +1,28 @@ +package org.ovirt.engine.core.common.vdscommands; + +import java.util.concurrent.TimeUnit; + +import org.ovirt.engine.core.compat.Guid; + +public class TimeBoundPollVDSCommandParameters extends VdsIdVDSCommandParametersBase { + private long timeout; + private TimeUnit unit; + + public TimeBoundPollVDSCommandParameters() { + } + + public TimeBoundPollVDSCommandParameters(Guid vdsId, long timeout, TimeUnit unit) { + super(vdsId); + this.timeout = timeout; + this.unit = unit; + } + + public long getTimeout() { + return timeout; + } + + public TimeUnit getUnit() { + return unit; + } + +} diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/FutureMap.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/FutureMap.java index 3a236ef..54a12c5 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/FutureMap.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/FutureMap.java @@ -44,9 +44,17 @@ super.put("code", 0); } }; + private Map<String, Object> timeoutStatus = new HashMap<String, Object>() { + { + super.put("message", "Internal timeout occured"); + super.put("code", -1); + } + }; private Class<?> clazz = new HashMap<String, Object>().getClass(); private Class<?> subTypeClazz; private boolean ignoreResponseKey = false; + private long timeout = 0; + private TimeUnit unit = TimeUnit.MILLISECONDS; /** * During creation request is sent and <code>Future</code> for a response is held. @@ -64,6 +72,25 @@ } /** + * During creation request is sent and <code>Future</code> for a response is held. + * + * @param client - Client object used to send request. + * @param request - Request to be sent. + * @param timeout - Timeout which is used when populating response map. + * @param unit - Time unit for timeout. + * @throws XmlRpcRunTimeException when there are connection issues. + */ + public FutureMap(JsonRpcClient client, JsonRpcRequest request, long timeout, TimeUnit unit) { + try { + this.timeout = timeout; + this.unit = unit; + this.response = client.call(request); + } catch (ClientConnectionException e) { + throw new XmlRpcRunTimeException("Connection issues during send request", e); + } + } + + /** * Whenever any method is executed to obtain value of response during the first invocation it gets real response * from the <code>Future</code> and decompose it to object of provided type and structure. * @@ -73,10 +100,16 @@ try (LockWrapper wrapper = new LockWrapper(this.lock)) { if (this.responseMap.isEmpty()) { try { - populate(this.response.get()); + if (timeout != 0) { + populate(this.response.get(timeout, unit)); + } else { + populate(this.response.get()); + } } catch (InterruptedException | ExecutionException e) { log.error("Exception occured during response decomposition", e); throw new IllegalStateException(e); + } catch (TimeoutException e) { + this.responseMap.put(STATUS, timeoutStatus); } } } diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java index 0fee690..59c249c 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java @@ -7,6 +7,7 @@ import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; import org.apache.commons.httpclient.HttpClient; import org.ovirt.engine.core.compat.Guid; @@ -909,12 +910,17 @@ @Override public FutureTask<Map<String, Object>> poll() { + return timeBoundPoll(0, TimeUnit.MILLISECONDS); + } + + @Override + public FutureTask<Map<String, Object>> timeBoundPoll(final long timeout, final TimeUnit unit) { final JsonRpcRequest request = new RequestBuilder("Host.ping").build(); final FutureCallable callable = new FutureCallable(new Callable<Map<String, Object>>() { @Override public Map<String, Object> call() throws Exception { - return new FutureMap(client, request); + return new FutureMap(client, request, timeout, unit); } }); diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java index 478a05b..839efd4 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java @@ -3,6 +3,7 @@ import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; import org.apache.commons.httpclient.HttpClient; import org.ovirt.engine.core.compat.Guid; @@ -185,6 +186,8 @@ FutureTask<Map<String, Object>> poll(); + FutureTask<Map<String, Object>> timeBoundPoll(long timeout, TimeUnit unit); + StatusOnlyReturnForXmlRpc snapshot(String vmId, Map<String, String>[] disks); StatusOnlyReturnForXmlRpc snapshot(String vmId, Map<String, String>[] disks, String memory); diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/TimeBoundPollVDSCommand.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/TimeBoundPollVDSCommand.java new file mode 100644 index 0000000..a19b69d --- /dev/null +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/TimeBoundPollVDSCommand.java @@ -0,0 +1,22 @@ +package org.ovirt.engine.core.vdsbroker.vdsbroker; + +import org.ovirt.engine.core.common.vdscommands.TimeBoundPollVDSCommandParameters; +import org.ovirt.engine.core.utils.log.Logged; +import org.ovirt.engine.core.utils.log.Logged.LogLevel; + +/** + * Sole purpose of this command is to check connectivity with VDSM by invoking poll verb. + */ +@Logged(executionLevel = LogLevel.TRACE, errorLevel = LogLevel.DEBUG) +public class TimeBoundPollVDSCommand<P extends TimeBoundPollVDSCommandParameters> extends FutureVDSCommand<P> { + + public TimeBoundPollVDSCommand(P parameters) { + super(parameters); + } + + @Override + protected void executeVdsBrokerCommand() { + httpTask = getBroker().timeBoundPoll(this.getParameters().getTimeout(), this.getParameters().getUnit()); + } + +} diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java index a061795..14e49c1 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; import org.apache.commons.httpclient.HttpClient; import org.ovirt.engine.core.compat.Guid; @@ -860,6 +861,11 @@ } @Override + public FutureTask<Map<String, Object>> timeBoundPoll(long timeout, TimeUnit unit) { + return poll(); + } + + @Override public StatusOnlyReturnForXmlRpc snapshot(String vmId, Map<String, String>[] disks) { try { Map<String, Object> xmlRpcReturnValue = vdsServer.snapshot(vmId, disks); -- To view, visit http://gerrit.ovirt.org/34098 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie6f48bec60b520c089f326f8c5e79aec288ff3d6 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Piotr Kliczewski <piotr.kliczew...@gmail.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches