package org.ovirt.engine.core.bll.network.host;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.ovirt.engine.core.bll.Backend;
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.VDSReturnValue;
import org.ovirt.engine.core.common.vdscommands.VdsIdVDSCommandParametersBase;
import org.ovirt.engine.core.compat.Guid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@code HostSetupNetworkPoller} class uses {@link FutureVDSCall} to poll the VDSM (with ping verb).
*/
public class HostSetupNetworkPoller {
private static final Logger LOGGER = LoggerFactory.getLogger(HostSetupNetworkPoller.class);
/**
* Time millis between polling attempts, to prevent flooding the host/network.
*/
private static final long POLLING_BREAK = 500;
private static final long POLLING_BREAK_IN_NANOS = TimeUnit.MILLISECONDS.toNanos(POLLING_BREAK);
private Long timestampOfEndOfPreviousInvocation;
public boolean poll(Guid hostId) {
waitBetweenPolls();
LOGGER.trace("Request to do poll for host {}.", hostId);
FutureVDSCall<VDSReturnValue> task =
Backend.getInstance()
.getResourceManager()
.runFutureVdsCommand(FutureVDSCommandType.Poll, new VdsIdVDSCommandParametersBase(hostId));
LOGGER.trace("FutureVDSCommandType.Poll executed for host{}.", hostId);
boolean succeeded = getValue(task);
LOGGER.trace("Result of FutureVDSCommandType.Poll for host {}: {}", hostId, succeeded);
timestampOfEndOfPreviousInvocation = currentTimestamp();
return succeeded;
}
/**
* @param task future to get value from.
*
* @return true if execution of task was a success, false if execution was not successful or wasn't completed in
* given timeout.
*/
private boolean getValue(FutureVDSCall<VDSReturnValue> task) {
try {
VDSReturnValue vdsReturnValue =
task.get(Config.<Integer> getValue(ConfigValues.SetupNetworksPollingTimeout), TimeUnit.SECONDS);
return vdsReturnValue.getSucceeded();
} catch (TimeoutException e) {
// VDSReturn value did not become available in given timeout. Ignore failure.
// network can go down due to VDSM changing the network.
return false;
}
}
private void waitBetweenPolls() {
/*
* Please notice, that thread sleep does not guarantee to return *only after* required time period passed.
* It may return sooner. When testing with required 500ms sleep, thread awaken after ~ 200ms, which is not even
* close.
* */
while (timestampOfEndOfPreviousInvocation != null
&& currentTimestamp() - timestampOfEndOfPreviousInvocation < POLLING_BREAK_IN_NANOS) {
try {
Thread.sleep(POLLING_BREAK);
} catch (InterruptedException e) {
// ignore.
}
}
}
private long currentTimestamp() {
return System.nanoTime();
}
}