deviceInfo.setDeviceUpdateHistory(deviceUpdateLog);
this.deviceUpdateHistory = deviceUpdateLog;
}
+
+ public TransactionInvoker getTxInvoker() {
+ return txInvoker;
+ }
}
private final HwvtepConnectionInstance connectionInstance;
+ private Map<InstanceIdentifier, AtomicInteger> iidInQueueCount = new ConcurrentHashMap<>();
private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData =
new ConcurrentHashMap<>();
private final Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> opKeyVsData =
return Collections.unmodifiableMap(uuidVsData);
}
+ public void putKeyInDependencyQueue(InstanceIdentifier iid) {
+ iidInQueueCount.putIfAbsent(iid, new AtomicInteger(0));
+ iidInQueueCount.get(iid).incrementAndGet();
+ }
+
+ public void clearKeyFromDependencyQueue(InstanceIdentifier iid) {
+ iidInQueueCount.remove(iid);
+ }
+
+ public boolean isKeyInDependencyQueue(InstanceIdentifier iid) {
+ return iidInQueueCount.containsKey(iid);
+ }
+
}
"config.node.update.max.delay.ms", 10000);
int EOS_TIMEOUT = Integer.getInteger("hwvtep.eos.timeout.delay.secs", 240);
int CHAIN_RETRY_COUNT = 10;
+ long LS_REMOVE_DELAY_SECS = 5;
+ int LS_REMOVE_RETRIES = 10;
}
package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
+import com.google.common.collect.Lists;
+
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepTableReader;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
-import org.opendaylight.ovsdb.utils.mdsal.utils.ControllerMdsalUtils;
import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
protected volatile HwvtepOperationalState hwvtepOperationalState = null;
protected volatile TransactionBuilder deviceTransaction = null;
private Collection<DataTreeModification<Node>> changes;
- protected Map<TransactionBuilder, List<MdsalUpdate<T>>> updates = new ConcurrentHashMap<>();
+ Set<MdsalUpdate<T>> updates = new HashSet<>();
protected AbstractTransactCommand() {
// NO OP
}
void updateCurrentTxDeleteData(Class<? extends Identifiable> cls, InstanceIdentifier key, T data) {
- getOperationalState().getDeviceInfo().markKeyAsInTransit(cls, key);
+ hwvtepOperationalState.updateCurrentTxDeleteData(cls, key);
+ markKeyAsInTransit(cls, key);
addToUpdates(key, data);
- getOperationalState().getDeviceInfo().clearConfigData(cls, key);
}
void updateCurrentTxData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid, T data) {
- getOperationalState().getDeviceInfo().markKeyAsInTransit(cls, key);
+ hwvtepOperationalState.updateCurrentTxData(cls, key, uuid);
+ markKeyAsInTransit(cls, key);
addToUpdates(key, data);
- getOperationalState().getDeviceInfo().updateConfigData(cls, key, data);
}
void addToUpdates(InstanceIdentifier key, T data) {
T oldData = null;
Type type = getClass().getGenericSuperclass();
Type classType = ((ParameterizedType) type).getActualTypeArguments()[0];
- if (getDeviceInfo().getConfigData((Class<? extends Identifiable>) classType, key) != null
- && getDeviceInfo().getConfigData((Class<? extends Identifiable>) classType, key).getData() != null) {
- oldData = (T) getDeviceInfo().getConfigData((Class<? extends Identifiable>) classType, key).getData();
+ if (getConfigData((Class<? extends Identifiable>) classType, key) != null) {
+ oldData = (T) getConfigData((Class<? extends Identifiable>) classType, key).getData();
}
- updates.putIfAbsent(getDeviceTransaction(), new ArrayList<MdsalUpdate<T>>());
- updates.get(getDeviceTransaction()).add(new MdsalUpdate<>(key, data, oldData));
+ updates.add(new MdsalUpdate<T>(key, data, oldData));
}
void processDependencies(final UnMetDependencyGetter<T> unMetDependencyGetter,
final InstanceIdentifier key,
final T data, final Object... extraData) {
- this.deviceTransaction = transaction;
- HwvtepDeviceInfo deviceInfo = getOperationalState().getDeviceInfo();
- Map inTransitDependencies = new HashMap<>();
- Map configDependencies = new HashMap<>();
-
- if (!isDeleteCmd() && unMetDependencyGetter != null) {
- inTransitDependencies = unMetDependencyGetter.getInTransitDependencies(getOperationalState(), data);
- configDependencies = unMetDependencyGetter.getUnMetConfigDependencies(getOperationalState(), data);
- //we can skip the config termination point dependency as we can create them in device as part of this tx
- configDependencies.remove(TerminationPoint.class);
- }
-
+ HwvtepDeviceInfo deviceInfo = hwvtepOperationalState.getDeviceInfo();
Type type = getClass().getGenericSuperclass();
Type classType = ((ParameterizedType) type).getActualTypeArguments()[0];
+ Map inTransitDependencies = Collections.emptyMap();
+ Map confingDependencies = Collections.emptyMap();
- //If this key itself is in transit wait for the response of this key itself
- if (deviceInfo.isKeyInTransit((Class<? extends Identifiable>) classType, key)) {
- inTransitDependencies.put(classType, Collections.singletonList(key));
- }
+ if (isDeleteCmd()) {
+ if (deviceInfo.isKeyInTransit((Class<? extends Identifiable>) classType, key)) {
+ inTransitDependencies = new HashMap<>();
+ inTransitDependencies.put((Class<? extends Identifiable>) classType, Lists.newArrayList(key));
+ }
+ } else {
+ inTransitDependencies = unMetDependencyGetter.getInTransitDependencies(hwvtepOperationalState, data);
+ confingDependencies = unMetDependencyGetter.getUnMetConfigDependencies(hwvtepOperationalState, data);
+ //we can skip the config termination point dependency as we can create them in device as part of this tx
+ confingDependencies.remove(TerminationPoint.class);
- if (HwvtepSouthboundUtil.isEmptyMap(configDependencies) && HwvtepSouthboundUtil.isEmptyMap(
- inTransitDependencies)) {
+ //If this key itself is in transit wait for the response of this key itself
+ if (deviceInfo.isKeyInTransit((Class<? extends Identifiable>) classType, key)
+ || deviceInfo.isKeyInDependencyQueue(key)) {
+ inTransitDependencies.put((Class<? extends Identifiable>) classType, Lists.newArrayList(key));
+ }
+ }
+ LOG.info("Update received for key: {} txId: {}", key, getOperationalState().getTransactionId());
+ if (HwvtepSouthboundUtil.isEmptyMap(confingDependencies)
+ && HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
doDeviceTransaction(transaction, nodeIid, data, key, extraData);
if (isDeleteCmd()) {
getDeviceInfo().clearConfigData((Class<? extends Identifiable>) classType, key);
getDeviceInfo().updateConfigData((Class<? extends Identifiable>) classType, key, data);
}
}
- if (!HwvtepSouthboundUtil.isEmptyMap(configDependencies)) {
- DependentJob<T> configWaitingJob = new DependentJob.ConfigWaitingJob<T>(
- key, data, configDependencies) {
+
+ if (!HwvtepSouthboundUtil.isEmptyMap(confingDependencies)) {
+ DependentJob<T> configWaitingJob = new DependentJob.ConfigWaitingJob(
+ key, data, confingDependencies) {
+ AbstractTransactCommand clone = getClone();
@Override
public void onDependencyResolved(HwvtepOperationalState operationalState,
- TransactionBuilder transactionBuilder) {
- hwvtepOperationalState = operationalState;
- deviceTransaction = transactionBuilder;
- onConfigUpdate(transactionBuilder, nodeIid, data, key, extraData);
+ TransactionBuilder transactionBuilder) {
+ clone.hwvtepOperationalState = operationalState;
+ HwvtepDeviceInfo.DeviceData deviceData =
+ getDeviceInfo().getConfigData((Class<? extends Identifiable>)getClassType(), key);
+ T latest = data;
+ if (deviceData != null && deviceData.getData() != null) {
+ latest = (T) deviceData.getData();
+ clone.onConfigUpdate(transactionBuilder, nodeIid, latest, key, extraData);
+ } else if (isDeleteCmd()) {
+ clone.onConfigUpdate(transactionBuilder, nodeIid, latest, key, extraData);
+ }
+ }
+
+ @Override
+ public void onFailure() {
+ clone.onFailure(transaction);
+ }
+
+ @Override
+ public void onSuccess() {
+ clone.onSuccess(transaction);
}
};
- deviceInfo.addJobToQueue(configWaitingJob);
+ LOG.info("Update Adding to config wait queue for key: {} txId: {}",
+ key, getOperationalState().getTransactionId());
+ addJobToQueue(configWaitingJob);
+ return;
}
-
+ final long transactionId = hwvtepOperationalState.getTransactionId();
if (!HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
- DependentJob<T> opWaitingJob = new DependentJob.OpWaitingJob<T>(
- key, data, inTransitDependencies) {
+ DependentJob<T> opWaitingJob = new DependentJob.OpWaitingJob(
+ key, data, inTransitDependencies, transactionId) {
+ AbstractTransactCommand clone = getClone();
@Override
public void onDependencyResolved(HwvtepOperationalState operationalState,
- TransactionBuilder transactionBuilder) {
- //data would have got deleted by , push the data only if it is still in configds
- hwvtepOperationalState = operationalState;
- deviceTransaction = transactionBuilder;
- T data = (T) new ControllerMdsalUtils(operationalState.getDataBroker()).read(
- LogicalDatastoreType.CONFIGURATION, key);
- if (data != null) {
- onConfigUpdate(transactionBuilder, nodeIid, data, key, extraData);
- } else {
- LOG.warn("Skipping add of key: {} as it is not present", key);
+ TransactionBuilder transactionBuilder) {
+ clone.hwvtepOperationalState = operationalState;
+ HwvtepDeviceInfo.DeviceData deviceData = getDeviceInfo()
+ .getConfigData((Class<? extends Identifiable>)getClassType(), key);
+ T latest = data;
+ if (deviceData != null && deviceData.getData() != null) {
+ latest = (T) deviceData.getData();
+ clone.onConfigUpdate(transactionBuilder, nodeIid, latest, key, extraData);
+ } else if (isDeleteCmd()) {
+ clone.onConfigUpdate(transactionBuilder, nodeIid, latest, key, extraData);
}
}
+
+ @Override
+ public void onFailure() {
+ clone.onFailure(transaction);
+ }
+
+ @Override
+ public void onSuccess() {
+ clone.onSuccess(transaction);
+ }
};
- deviceInfo.addJobToQueue(opWaitingJob);
+ LOG.info("Update Adding to op wait queue for key: {} txId: {}", key, transactionId);
+ addJobToQueue(opWaitingJob);
+ return;
}
}
if (modification != null && !modification.isEmpty()) {
for (DataTreeModification<Node> change : modification) {
final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+ if (!Objects.equals(hwvtepOperationalState.getConnectionInstance().getInstanceIdentifier(), key)) {
+ continue;
+ }
Class<? extends Identifiable> classType = (Class<? extends Identifiable>) getClassType();
List<T> removed;
if (getOperationalState().isInReconciliation()) {
if (modification != null && !modification.isEmpty()) {
for (DataTreeModification<Node> change : modification) {
InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+ if (!Objects.equals(hwvtepOperationalState.getConnectionInstance().getInstanceIdentifier(), key)) {
+ continue;
+ }
Class<? extends Identifiable> classType = (Class<? extends Identifiable>) getClassType();
List<T> updated = null;
if (getOperationalState().isInReconciliation()) {
List<T> data1 = getData(include);
List<T> data2 = diffOf(node1, node2, compareKeyOnly);
if (HwvtepSouthboundUtil.isEmpty(data1) && HwvtepSouthboundUtil.isEmpty(data2)) {
- return Collections.emptyList();
+ return Collections.EMPTY_LIST;
}
List<T> result = new ArrayList<>(data1);
result.addAll(data2);
List<T> list2 = getData(node2);
if (HwvtepSouthboundUtil.isEmpty(list1)) {
- return Collections.emptyList();
+ return Collections.EMPTY_LIST;
}
if (HwvtepSouthboundUtil.isEmpty(list2)) {
- return HwvtepSouthboundUtil.isEmpty(list1) ? Collections.emptyList() : list1;
+ return HwvtepSouthboundUtil.isEmpty(list1) ? Collections.EMPTY_LIST : list1;
}
- Iterator<T> it1 = list1.iterator();
-
- while (it1.hasNext()) {
- T ele = it1.next();
- Iterator<T> it2 = list2.iterator();
- boolean found = false;
- while (it2.hasNext()) {
- T other = it2.next();
- found = compareKeyOnly ? Objects.equals(ele.key(), other.key()) : areEqual(ele, other);
- if (found) {
- it2.remove();
- break;
+ Map<Object, T> map1 = list1.stream().collect(Collectors.toMap(ele -> ele.key(), ele -> ele));
+ Map<Object, T> map2 = list2.stream().collect(Collectors.toMap(ele -> ele.key(), ele -> ele));
+ map1.entrySet().forEach(entry1 -> {
+ T val2 = map2.remove(entry1.getKey());
+ if (compareKeyOnly) {
+ if (val2 == null) {
+ result.add(entry1.getValue());
+ }
+ } else {
+ if (val2 == null) {
+ result.add(entry1.getValue());
+ return;
+ }
+ if (!areEqual(entry1.getValue(), val2)) {
+ result.add(entry1.getValue());
}
}
- if (!found) {
- result.add(ele);
- }
- }
+ });
return result;
}
@Override
public void onSuccess(TransactionBuilder deviceTx) {
- if (deviceTx == null || !updates.containsKey(deviceTx)) {
- return;
- }
onCommandSucceeded();
}
@Override
public void onFailure(TransactionBuilder deviceTx) {
- if (deviceTx == null || !updates.containsKey(deviceTx)) {
- return;
- }
- for (MdsalUpdate mdsalUpdate : updates.get(deviceTx)) {
- getDeviceInfo().clearInTransit((Class<? extends Identifiable>) mdsalUpdate.getClass(),
- mdsalUpdate.getKey());
- }
onCommandFailed();
}
public <T> HwvtepDeviceInfo.DeviceData fetchDeviceData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
HwvtepDeviceInfo.DeviceData deviceData = getDeviceOpData(cls, key);
if (deviceData == null) {
- LOG.debug("Could not find data for key {}", getNodeKeyStr(key));
- java.util.Optional<TypedBaseTable> optional = getTableReader().getHwvtepTableEntryUUID(cls, key, null);
+ LOG.debug("Could not find data for key {}", key);
+ java.util.Optional<TypedBaseTable> optional =
+ getTableReader().getHwvtepTableEntryUUID(cls, key, null);
if (optional.isPresent()) {
- LOG.debug("Found the data for key from device {} ", getNodeKeyStr(key));
+ LOG.debug("Found the data for key from device {} ", key);
getDeviceInfo().updateDeviceOperData(cls, key, optional.get().getUuid(), (T)optional.get());
return getDeviceOpData(cls, key);
} else {
- LOG.info("Could not Find the data for key from device {} ", getNodeKeyStr(key));
+ LOG.info("Could not Find the data for key from device {} ", key);
}
}
return deviceData;
}
- protected String getNodeKeyStr(InstanceIdentifier iid) {
- try {
- return getClassType().getTypeName() + "." + ((Node) iid.firstKeyOf(Node.class)).getNodeId().getValue() + "."
- + getKeyStr(iid);
- } catch (ClassCastException exp) {
- LOG.error("Error in getting the Node id ", exp);
- }
+ protected String getKeyStr(InstanceIdentifier iid) {
return iid.toString();
}
- protected String getKeyStr(InstanceIdentifier iid) {
- return iid.toString();
+ public <K extends Identifiable> void addJobToQueue(DependentJob<K> job) {
+ hwvtepOperationalState.getDeviceInfo().putKeyInDependencyQueue(job.getKey());
+ hwvtepOperationalState.getDeviceInfo().addJobToQueue(job);
+ }
+
+ public void markKeyAsInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ hwvtepOperationalState.getDeviceInfo().markKeyAsInTransit(cls, key);
}
public HwvtepDeviceInfo.DeviceData getDeviceOpData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
return getOperationalState().getDeviceInfo().getDeviceOperData(cls, key);
}
+ public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ hwvtepOperationalState.getDeviceInfo().clearConfigData(cls, key);
+ }
+
+ public HwvtepDeviceInfo.DeviceData getConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ return hwvtepOperationalState.getDeviceInfo().getConfigData(cls, key);
+ }
+
+ public void updateConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key, Object data) {
+ hwvtepOperationalState.getDeviceInfo().updateConfigData(cls, key, data);
+ }
+
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public AbstractTransactCommand getClone() {
+ try {
+ return (AbstractTransactCommand) getClass().getConstructor(HwvtepOperationalState.class, Collection.class)
+ .newInstance(hwvtepOperationalState, changes);
+ } catch (Throwable e) {
+ LOG.error("Failed to clone the cmd ", e);
+ }
+ return this;
+ }
+
public HwvtepTableReader getTableReader() {
return getOperationalState().getConnectionInstance().getHwvtepTableReader();
}
+
+ public HwvtepConnectionInstance getConnectionInstance() {
+ return hwvtepOperationalState.getConnectionInstance();
+ }
+
+ public HwvtepOperationalState newOperState() {
+ return new HwvtepOperationalState(getConnectionInstance());
+ }
}
package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
processReadyJobs(connectionInstance, opWaitQueue);
}
+ @SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
private void processReadyJobs(final HwvtepConnectionInstance hwvtepConnectionInstance,
LinkedBlockingQueue<DependentJob> queue) {
- final List<DependentJob> readyJobs = getReadyJobs(queue);
- if (readyJobs.size() > 0) {
- EXECUTOR_SERVICE.execute(() -> hwvtepConnectionInstance.transact(new TransactCommand() {
- private HwvtepOperationalState operationalState;
-
- @Override
- public void execute(TransactionBuilder transactionBuilder) {
- this.operationalState = new HwvtepOperationalState(hwvtepConnectionInstance);
- for (DependentJob job : readyJobs) {
- job.onDependencyResolved(operationalState, transactionBuilder);
+ final List<DependentJob> readyJobs = getReadyJobs(queue);
+ readyJobs.forEach((job) -> {
+ EXECUTOR_SERVICE.execute(() ->
+ hwvtepConnectionInstance.transact(new TransactCommand() {
+ HwvtepOperationalState operationalState = new HwvtepOperationalState(hwvtepConnectionInstance);
+ AtomicInteger retryCount = new AtomicInteger(5);
+
+ @Override
+ public boolean retry() {
+ return retryCount.decrementAndGet() > 0;
}
- }
- @Override
- public void onFailure(TransactionBuilder deviceTransaction) {
- readyJobs.forEach((job) -> job.onFailure(deviceTransaction));
- if (operationalState != null) {
+ @Override
+ public void execute(TransactionBuilder transactionBuilder) {
+ deviceInfo.clearKeyFromDependencyQueue(job.getKey());
+ if (operationalState.getConnectionInstance() != null
+ && operationalState.getConnectionInstance().isActive()) {
+ job.onDependencyResolved(operationalState, transactionBuilder);
+ }
+ }
+
+ @Override
+ @SuppressFBWarnings(value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR")
+ public void onFailure(TransactionBuilder tx) {
+ job.onFailure();
operationalState.clearIntransitKeys();
+
}
- }
- @Override
- public void onSuccess(TransactionBuilder deviceTransaction) {
- readyJobs.forEach((job) -> job.onSuccess(deviceTransaction));
- if (operationalState != null) {
+ @Override
+ public void onSuccess(TransactionBuilder tx) {
+ job.onSuccess();
operationalState.getDeviceInfo().onOperDataAvailable();
}
- }
- }));
- }
+ }));
+ });
}
private List<DependentJob> getReadyJobs(LinkedBlockingQueue<DependentJob> queue) {
while (jobIterator.hasNext()) {
DependentJob job = jobIterator.next();
long currentTime = System.currentTimeMillis();
-
- //first check if its dependencies are met later check for expired status
if (job.areDependenciesMet(deviceInfo)) {
jobIterator.remove();
readyJobs.add(job);
continue;
}
if (job.isExpired(currentTime)) {
+ deviceInfo.clearKeyFromDependencyQueue(job.getKey());
jobIterator.remove();
continue;
}
private final InstanceIdentifier key;
private final T data;
private final Map<Class<? extends DataObject>, List<InstanceIdentifier>> dependencies;
+ private final long transactionId;
DependentJob(InstanceIdentifier key,
- T data, Map<Class<? extends DataObject>, List<InstanceIdentifier>> dependencies) {
+ T data, Map<Class<? extends DataObject>, List<InstanceIdentifier>> dependencies,
+ long transactionId) {
this.expiryTime = System.currentTimeMillis() + HwvtepSouthboundConstants.WAITING_JOB_EXPIRY_TIME_MILLIS;
this.key = key;
this.data = data;
this.dependencies = dependencies;
+ this.transactionId = transactionId;
}
/**
return key;
}
+ public long getTransactionId() {
+ return transactionId;
+ }
+
+ public Map<Class<? extends DataObject>, List<InstanceIdentifier>> getDependencies() {
+ return dependencies;
+ }
+
public T getData() {
return data;
}
return true;
}
- public void onFailure(TransactionBuilder deviceTransaction) {
+ public void onFailure() {
}
- public void onSuccess(TransactionBuilder deviceTransaction) {
+ public void onSuccess() {
}
public abstract static class ConfigWaitingJob<T extends Identifiable> extends DependentJob<T> {
public ConfigWaitingJob(InstanceIdentifier key, T data,
Map<Class<? extends DataObject>, List<InstanceIdentifier>> dependencies) {
- super(key, data, dependencies);
+ super(key, data, dependencies, 0);
}
@Override
protected boolean isDependencyMet(HwvtepDeviceInfo deviceInfo, Class cls, InstanceIdentifier iid) {
return deviceInfo.isConfigDataAvailable(cls, iid);
}
+
+ public boolean isConfigWaitingJob() {
+ return true;
+ }
}
public abstract static class OpWaitingJob<T extends Identifiable> extends DependentJob<T> {
public OpWaitingJob(InstanceIdentifier key, T data,
- Map<Class<? extends DataObject>, List<InstanceIdentifier>> dependencies) {
- super(key, data, dependencies);
+ Map<Class<? extends DataObject>, List<InstanceIdentifier>> dependencies,
+ long transactionId) {
+ super(key, data, dependencies, transactionId);
}
@Override
private boolean inReconciliation = false;
private final DataBroker db;
private final Collection<DataTreeModification<Node>> changes;
+ long transactionId = 0;
public HwvtepOperationalState(DataBroker db, HwvtepConnectionInstance connectionInstance,
Collection<DataTreeModification<Node>> changes) {
currentTxDeletedKeys.clear();
deviceInfo.onOperDataAvailable();
}
+
+ public long getTransactionId() {
+ return transactionId;
+ }
}
*/
package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
-import static org.opendaylight.ovsdb.lib.operations.Operations.op;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
-import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
-import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
-import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
-import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
-import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsLocal;
-import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
-import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsLocal;
-import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
-import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
public class LogicalSwitchRemoveCommand extends AbstractTransactCommand<LogicalSwitches, HwvtepGlobalAugmentation> {
private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchRemoveCommand.class);
+ List<LogicalSwitches> deletedLs;
public LogicalSwitchRemoveCommand(final HwvtepOperationalState state,
final Collection<DataTreeModification<Node>> changes) {
@Override
public void execute(final TransactionBuilder transaction) {
Map<InstanceIdentifier<Node>, List<LogicalSwitches>> removeds =
- extractRemoved(getChanges(),LogicalSwitches.class);
-
- for (Entry<InstanceIdentifier<Node>, List<LogicalSwitches>> created: removeds.entrySet()) {
- if (!HwvtepSouthboundUtil.isEmpty(created.getValue())) {
- HwvtepConnectionInstance connectionInstance = getDeviceInfo().getConnectionInstance();
- getDeviceInfo().scheduleTransaction(new TransactCommand() {
- @Override
- public void execute(final TransactionBuilder transactionBuilder) {
- HwvtepOperationalState operState = new HwvtepOperationalState(
- connectionInstance.getDataBroker(), connectionInstance, Collections.EMPTY_LIST);
- hwvtepOperationalState = operState;
- deviceTransaction = deviceTransaction;
- LOG.debug("Running delete logical switch in seperate tx {}", created.getKey());
- removeLogicalSwitch(transactionBuilder, created.getKey(), created.getValue());
- }
-
- @Override
- public void onSuccess(final TransactionBuilder deviceTransaction) {
- LogicalSwitchRemoveCommand.this.onSuccess(deviceTransaction);
- }
-
- @Override
- public void onFailure(final TransactionBuilder deviceTransaction) {
- LogicalSwitchRemoveCommand.this.onFailure(deviceTransaction);
- }
- });
+ extractRemoved(getChanges(), LogicalSwitches.class);
+ if (removeds != null) {
+ for (Entry<InstanceIdentifier<Node>, List<LogicalSwitches>> deleted: removeds.entrySet()) {
+ deletedLs = deleted.getValue();
+ for (LogicalSwitches lswitch : deleted.getValue()) {
+ InstanceIdentifier<LogicalSwitches> lsKey =
+ deleted.getKey().augmentation(HwvtepGlobalAugmentation.class)
+ .child(LogicalSwitches.class, lswitch.key());
+ getDeviceInfo().clearConfigData(LogicalSwitches.class, lsKey);
+ onConfigUpdate(transaction, deleted.getKey(), lswitch, lsKey);
+ }
}
}
}
- @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
- justification = "https://github.com/spotbugs/spotbugs/issues/811")
- private void removeLogicalSwitch(final TransactionBuilder transaction,
- final InstanceIdentifier<Node> nodeIid, final List<LogicalSwitches> lswitchList) {
- for (LogicalSwitches lswitch: lswitchList) {
- InstanceIdentifier<LogicalSwitches> lsKey = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
- .child(LogicalSwitches.class, lswitch.key());
- onConfigUpdate(transaction, nodeIid, lswitch, lsKey);
- }
- }
-
@Override
- public void onConfigUpdate(final TransactionBuilder transaction,
- final InstanceIdentifier<Node> nodeIid,
- final LogicalSwitches lswitch,
- final InstanceIdentifier lsKey,
- final Object... extraData) {
- processDependencies(null, transaction, nodeIid, lsKey, lswitch);
+ public void onConfigUpdate(TransactionBuilder transaction, InstanceIdentifier<Node> nodeIid,
+ LogicalSwitches logicalSwitches, InstanceIdentifier lsKey, Object... extraData) {
+ processDependencies(EmptyDependencyGetter.INSTANCE, transaction, nodeIid, lsKey, logicalSwitches);
}
@Override
final LogicalSwitches lswitch,
final InstanceIdentifier lsKey,
final Object... extraData) {
- LOG.debug("Removing logical switch named: {}", lswitch.getHwvtepNodeName().getValue());
- HwvtepDeviceInfo.DeviceData deviceData = getOperationalState().getDeviceInfo().getDeviceOperData(
- LogicalSwitches.class, lsKey);
- LogicalSwitch logicalSwitch = transaction.getTypedRowSchema(LogicalSwitch.class);
-
- if (deviceData != null && deviceData.getUuid() != null) {
- UUID logicalSwitchUuid = deviceData.getUuid();
- transaction.add(op.delete(logicalSwitch.getSchema())
- .where(logicalSwitch.getUuidColumn().getSchema().opEqual(logicalSwitchUuid)).build());
-
- UcastMacsRemote ucastMacsRemote = transaction.getTypedRowSchema(UcastMacsRemote.class);
- transaction.add(op.delete(ucastMacsRemote.getSchema())
- .where(ucastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
-
- UcastMacsLocal ucastMacsLocal = transaction.getTypedRowSchema(UcastMacsLocal.class);
- transaction.add(op.delete(ucastMacsLocal.getSchema())
- .where(ucastMacsLocal.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
-
- McastMacsRemote mcastMacsRemote = transaction.getTypedRowSchema(McastMacsRemote.class);
- transaction.add(op.delete(mcastMacsRemote.getSchema())
- .where(mcastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
-
- McastMacsLocal mcastMacsLocal = transaction.getTypedRowSchema(McastMacsLocal.class);
- transaction.add(op.delete(mcastMacsLocal.getSchema())
- .where(mcastMacsLocal.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
- updateCurrentTxDeleteData(LogicalSwitches.class, lsKey, lswitch);
- updateControllerTxHistory(TransactionType.DELETE, lswitch);
- } else {
- LOG.warn("Unable to delete logical switch {} because it was not found in the operational store",
- lswitch.getHwvtepNodeName().getValue());
- }
+ LogicalSwitchUcastsRemoveCommand cmd = new LogicalSwitchUcastsRemoveCommand(
+ newOperState(), getChanges(), deletedLs, lswitch);
+ markKeyAsInTransit(LogicalSwitches.class, lsKey);
+ clearConfigData(LogicalSwitches.class, lsKey);
+ hwvtepOperationalState.getConnectionInstance().transact(cmd);
}
@Override
@Override
public void onCommandSucceeded() {
- if (getDeviceTransaction() == null || !updates.containsKey(getDeviceTransaction())) {
- return;
- }
- for (MdsalUpdate mdsalUpdate : updates.get(getDeviceTransaction())) {
+ for (MdsalUpdate mdsalUpdate : updates) {
getDeviceInfo().clearLogicalSwitchRefs(mdsalUpdate.getKey());
}
}
--- /dev/null
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
+import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsLocal;
+import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
+import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
+import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsLocal;
+import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LogicalSwitchUcastsRemoveCommand
+ extends AbstractTransactCommand<LogicalSwitches, HwvtepGlobalAugmentation> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchUcastsRemoveCommand.class);
+
+ volatile Map<String, Map<Long, UUID>> updatedPortBindings = new HashMap<>();
+ private AtomicInteger retryCount = new AtomicInteger(5);
+ private LogicalSwitches logicalSwitches;
+ private InstanceIdentifier<Node> nodeIid;
+ private List<LogicalSwitches> deletedLs;
+ private boolean firstAttempt = true;
+
+ public LogicalSwitchUcastsRemoveCommand(HwvtepOperationalState state,
+ Collection<DataTreeModification<Node>> changes,
+ List<LogicalSwitches> deletedLs,
+ LogicalSwitches logicalSwitches) {
+ super(state, changes);
+ this.deletedLs = deletedLs;
+ this.logicalSwitches = logicalSwitches;
+ this.nodeIid = getOperationalState().getConnectionInstance().getInstanceIdentifier();
+ }
+
+ @Override
+ public void execute(TransactionBuilder transaction) {
+ InstanceIdentifier<LogicalSwitches> lsKey = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
+ .child(LogicalSwitches.class, logicalSwitches.key());
+ HwvtepDeviceInfo.DeviceData deviceData = super.<LogicalSwitch>fetchDeviceData(LogicalSwitches.class, lsKey);
+ if (deviceData != null && deviceData.getUuid() != null) {
+
+ UUID logicalSwitchUuid = deviceData.getUuid();
+
+ UcastMacsRemote ucastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+ UcastMacsRemote.class, null);
+ transaction.add(op.delete(ucastMacsRemote.getSchema())
+ .where(ucastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
+
+ UcastMacsLocal ucastMacsLocal = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+ UcastMacsLocal.class, null);
+ transaction.add(op.delete(ucastMacsLocal.getSchema())
+ .where(ucastMacsLocal.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
+
+ McastMacsRemote mcastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+ McastMacsRemote.class, null);
+ transaction.add(op.delete(mcastMacsRemote.getSchema())
+ .where(mcastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
+
+ McastMacsLocal mcastMacsLocal = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+ McastMacsLocal.class, null);
+ transaction.add(op.delete(mcastMacsLocal.getSchema())
+ .where(mcastMacsLocal.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUuid)).build());
+
+ if (firstAttempt) {
+ LogicalSwitch logicalSwitch = TyperUtils.getTypedRowWrapper(
+ transaction.getDatabaseSchema(), LogicalSwitch.class, null);
+ transaction.add(op.delete(logicalSwitch.getSchema()).where(logicalSwitch.getNameColumn().getSchema()
+ .opEqual(logicalSwitches.getHwvtepNodeName().getValue())).build());
+ updateControllerTxHistory(TransactionType.DELETE, new StringBuilder(logicalSwitch.toString())
+ .append(": ").append(logicalSwitches.getHwvtepNodeName()).append(" ")
+ .append(logicalSwitches.getLogicalSwitchUuid()).append(" ")
+ .append(logicalSwitches.getTunnelKey()));
+ LOG.info("CONTROLLER - {} {} {} {} {}", TransactionType.DELETE, logicalSwitch,
+ logicalSwitches.getHwvtepNodeName(), logicalSwitches.getLogicalSwitchUuid(),
+ logicalSwitches.getTunnelKey());
+ } else {
+ for (Entry<String, Map<Long, UUID>> entry : updatedPortBindings.entrySet()) {
+ PhysicalPort physicalPort = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+ PhysicalPort.class);
+ physicalPort.setName(entry.getKey());
+ physicalPort.setVlanBindings(entry.getValue());
+ transaction.add(op.update(physicalPort)
+ .where(physicalPort.getNameColumn().getSchema().opEqual(physicalPort.getName())).build());
+ updateControllerTxHistory(TransactionType.UPDATE, physicalPort);
+ LOG.info("CONTROLLER - {} {}", TransactionType.UPDATE, physicalPort);
+ }
+ }
+ } else {
+ firstAttempt = false;
+ onSuccess(transaction);
+ }
+ }
+
+ @Override
+ protected List<LogicalSwitches> getData(HwvtepGlobalAugmentation augmentation) {
+ return augmentation.getLogicalSwitches();
+ }
+
+ @Override
+ protected boolean areEqual(LogicalSwitches logicalSwitches1 , LogicalSwitches logicalSwitches2) {
+ return logicalSwitches1.key().equals(logicalSwitches2.key())
+ && Objects.equals(logicalSwitches1.getTunnelKey(), logicalSwitches2.getTunnelKey());
+ }
+
+ @Override
+ public void onSuccess(TransactionBuilder tx) {
+ if (firstAttempt) {
+ //LOG.error("check succeeded in deletion of logical swtich at first attempt ");
+ //succeed in removing the logical switch upon first attempt
+ return;
+ }
+ //LOG.error("check succeeded in deletion of logical swtich after first attempt ");
+ PlainLogicalSwitchRemoveCmd cmd = new PlainLogicalSwitchRemoveCmd(
+ newOperState(), getChanges(), logicalSwitches, HwvtepSouthboundConstants.LS_REMOVE_RETRIES);
+ hwvtepOperationalState.getConnectionInstance().transact(cmd);
+ }
+
+ @Override
+ public void onFailure(TransactionBuilder tx) {
+ //Failed to remove logical swith upon first attempt,
+ //will attempt to remove the local ucasts and vlan bindings alone in the next attemtps
+ firstAttempt = false;
+ getFreshPortBindingsExcludingDeleted();
+ super.onFailure(tx);
+ }
+
+ private void getFreshPortBindingsExcludingDeleted() {
+ Set<UUID> deletedLsUuids = new HashSet<>();
+ for (LogicalSwitches ls : deletedLs) {
+ InstanceIdentifier<LogicalSwitches> lsKey = nodeIid
+ .augmentation(HwvtepGlobalAugmentation.class)
+ .child(LogicalSwitches.class, ls.key());
+ HwvtepDeviceInfo.DeviceData deviceData =
+ super.<LogicalSwitch>fetchDeviceData(LogicalSwitches.class, lsKey);
+ if (deviceData.getUuid() != null) {
+ deletedLsUuids.add(deviceData.getUuid());
+ }
+ }
+ updatedPortBindings = new HashMap<>();
+ List<TypedBaseTable> portsFromDevice = getOperationalState().getConnectionInstance()
+ .getHwvtepTableReader().getHwvtepTableEntries(VlanBindings.class);
+ if (portsFromDevice == null || portsFromDevice.isEmpty()) {
+ LOG.debug("Check did not get any bindings from tor while doing failure of logical switch delete");
+ return;
+ }
+ portsFromDevice.stream()
+ .map(row -> (PhysicalPort) row)
+ .filter(port -> port.getVlanBindingsColumn() != null && port.getVlanBindingsColumn().getData() != null)
+ .forEach(port -> {
+ int originalBindingsSize = port.getVlanBindingsColumn().getData().size();
+ Map<Long, UUID> bindingsAfterExclusion = excludeVlanBindings(deletedLsUuids, port);
+ if (bindingsAfterExclusion.size() < originalBindingsSize) {
+ updatedPortBindings.put(port.getName(), bindingsAfterExclusion);
+ }
+ });
+ }
+
+ private Map<Long, UUID> excludeVlanBindings(Set<UUID> deletedLsUuids, PhysicalPort port) {
+ return port.getVlanBindingsColumn().getData()
+ .entrySet().stream()
+ .peek(entry -> {
+ if (deletedLsUuids.contains(entry.getValue())) {
+ LOG.trace("check Excluding the vlan binding {}", entry.getValue());
+ }
+ })
+ .filter(entry -> !deletedLsUuids.contains(entry.getValue()))
+ .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));
+ }
+
+ public boolean retry() {
+ boolean ret = retryCount.decrementAndGet() > 0;
+ return ret;
+ }
+
+ protected boolean isDeleteCmd() {
+ return true;
+ }
+
+}
import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
final InstanceIdentifier macIid,
final Object... extraData) {
LOG.debug("Removing remoteMcastMacs, mac address: {}", mac.getMacEntryKey().getValue());
+ clearConfigData(RemoteMcastMacs.class, macIid);
HwvtepDeviceInfo.DeviceData operationalMacOptional =
getDeviceInfo().getDeviceOperData(RemoteMcastMacs.class, macIid);
McastMacsRemote mcastMacsRemote = transaction.getTypedRowSchema(McastMacsRemote.class);
return true;
}
-
- @Override
- public void onCommandSucceeded() {
- //remove the refcounts of the deleted macs
- for (MdsalUpdate mdsalUpdate : updates.get(getDeviceTransaction())) {
- RemoteMcastMacs deletedMac = (RemoteMcastMacs) mdsalUpdate.getNewData();
- InstanceIdentifier<RemoteMcastMacs> macIid = mdsalUpdate.getKey();
- getDeviceInfo().removeRemoteMcast(
- (InstanceIdentifier<LogicalSwitches>) deletedMac.getLogicalSwitchRef().getValue(), macIid);
- }
- }
}
final InstanceIdentifier<Node> instanceIdentifier, final List<RemoteMcastMacs> macList) {
for (RemoteMcastMacs mac: macList) {
//add / update only if locator set got changed
+ InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier
+ .augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteMcastMacs.class, mac.key());
+ updateConfigData(RemoteMcastMacs.class, macIid, mac);
if (!HwvtepSouthboundUtil.isEmpty(mac.getLocatorSet())) {
onConfigUpdate(transaction, instanceIdentifier, mac, null);
}
LOG.warn("Unable to update remoteMcastMacs {} because uuid not found in the operational store",
mac.getMacEntryKey().getValue());
}
+ InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteMcastMacs.class, mac.key());
+ updateConfigData(RemoteMcastMacs.class, macIid, mac);
}
private void setLogicalSwitch(final TransactionBuilder transaction, final McastMacsRemote mcastMacsRemote,
}
@Override
- protected void onCommandSucceeded() {
- for (MdsalUpdate mdsalUpdate : updates.get(getDeviceTransaction())) {
+ public void onSuccess(TransactionBuilder tx) {
+ for (MdsalUpdate mdsalUpdate : updates) {
updateLocatorRefCounts(mdsalUpdate);
RemoteMcastMacs mac = (RemoteMcastMacs) mdsalUpdate.getNewData();
InstanceIdentifier<RemoteMcastMacs> macIid = mdsalUpdate.getKey();
(InstanceIdentifier<LogicalSwitches>) mac.getLogicalSwitchRef().getValue(), macIid, mac);
}
}
+
}
final InstanceIdentifier<VlanBindings> vlanIid) {
DependentJob<VlanBindings> opWaitingJob = new DependentJob.OpWaitingJob<VlanBindings>(
- vlanIid, vlanBinding, inTransitDependencies) {
+ vlanIid, vlanBinding, inTransitDependencies, getOperationalState().getTransactionId()) {
@Override
public void onDependencyResolved(final HwvtepOperationalState operationalState,
final TransactionBuilder transactionBuilder) {
--- /dev/null
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
+import org.opendaylight.ovsdb.utils.mdsal.utils.Scheduler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PlainLogicalSwitchRemoveCmd extends AbstractTransactCommand<LogicalSwitches, HwvtepGlobalAugmentation> {
+ private static final Logger LOG = LoggerFactory.getLogger(PlainLogicalSwitchRemoveCmd.class);
+ private AtomicInteger retryCount = new AtomicInteger(5);
+ private LogicalSwitches logicalSwitches;
+ private InstanceIdentifier<Node> nodeIid;
+
+ public PlainLogicalSwitchRemoveCmd(HwvtepOperationalState state,
+ Collection<DataTreeModification<Node>> changes,
+ LogicalSwitches logicalSwitches,
+ int retryCount) {
+ super(state, changes);
+ this.logicalSwitches = logicalSwitches;
+ this.retryCount = new AtomicInteger(retryCount);
+ this.nodeIid = getOperationalState().getConnectionInstance().getInstanceIdentifier();
+ }
+
+ @Override
+ public void execute(TransactionBuilder transaction) {
+ LogicalSwitch logicalSwitch = TyperUtils.getTypedRowWrapper(
+ transaction.getDatabaseSchema(), LogicalSwitch.class, null);
+ transaction.add(op.delete(logicalSwitch.getSchema())
+ .where(logicalSwitch.getNameColumn().getSchema().opEqual(
+ logicalSwitches.getHwvtepNodeName().getValue())).build());
+ }
+
+ @Override
+ protected List<LogicalSwitches> getData(HwvtepGlobalAugmentation augmentation) {
+ return augmentation.getLogicalSwitches();
+ }
+
+ @Override
+ protected boolean areEqual(LogicalSwitches logicalSwitches1 , LogicalSwitches logicalSwitches2) {
+ return logicalSwitches1.key().equals(logicalSwitches2.key())
+ && Objects.equals(logicalSwitches1.getTunnelKey(), logicalSwitches2.getTunnelKey());
+ }
+
+ public boolean retry() {
+ boolean ret = retryCount.decrementAndGet() > 0;
+ if (ret) {
+ Scheduler.getScheduledExecutorService().schedule(() -> {
+ getOperationalState().getConnectionInstance().transact(this);
+ }, HwvtepSouthboundConstants.LS_REMOVE_DELAY_SECS, TimeUnit.SECONDS);
+ } else {
+ LOG.error("Failed in deletion of logical switch {}", logicalSwitches);
+ }
+ return ret;
+ }
+
+ protected boolean isDeleteCmd() {
+ return true;
+ }
+}
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
return true;
}
- @Override
- public void onCommandSucceeded() {
- for (MdsalUpdate mdsalUpdate : updates.get(getDeviceTransaction())) {
- RemoteUcastMacs deletedMac = (RemoteUcastMacs) mdsalUpdate.getNewData();
- InstanceIdentifier<RemoteUcastMacs> macIid = mdsalUpdate.getKey();
- getDeviceInfo().removeRemoteUcast(
- (InstanceIdentifier<LogicalSwitches>) deletedMac.getLogicalSwitchRef().getValue(), macIid);
- }
- }
}
final InstanceIdentifier macKey,
final Object... extraData) {
LOG.debug("Creating remoteUcastMacs, mac address: {}", remoteUcastMac.getMacEntryKey().getValue());
+ updateConfigData(RemoteUcastMacs.class, macKey, remoteUcastMac);
final HwvtepDeviceInfo.DeviceData deviceData =
getOperationalState().getDeviceInfo().getDeviceOperData(RemoteUcastMacs.class, macKey);
}
@Override
- public void onCommandSucceeded() {
- for (MdsalUpdate mdsalUpdate : updates.get(getDeviceTransaction())) {
- RemoteUcastMacs newMac = (RemoteUcastMacs) mdsalUpdate.getNewData();
+ public void onSuccess(TransactionBuilder tx) {
+ for (MdsalUpdate mdsalUpdate : updates) {
+ RemoteUcastMacs mac = (RemoteUcastMacs) mdsalUpdate.getNewData();
InstanceIdentifier<RemoteUcastMacs> macIid = mdsalUpdate.getKey();
- RemoteUcastMacs oldMac = (RemoteUcastMacs) mdsalUpdate.getOldData();
- if (oldMac != null && !oldMac.equals(newMac)) {
- getDeviceInfo().decRefCount(macIid, oldMac.getLocatorRef().getValue());
- }
getDeviceInfo().updateRemoteUcast(
- (InstanceIdentifier<LogicalSwitches>) newMac.getLogicalSwitchRef().getValue(), macIid, newMac);
+ (InstanceIdentifier<LogicalSwitches>) mac.getLogicalSwitchRef().getValue(), macIid, mac);
}
}
}
final CountDownLatch latch = new CountDownLatch(1);
opState.getDeviceInfo().addJobToQueue(new DependentJob.OpWaitingJob<RemoteMcastMacs>(
- macIid, mac, (Map)unMetDependencies) {
+ macIid, mac, (Map)unMetDependencies, 0) {
@Override
protected void onDependencyResolved(HwvtepOperationalState operationalState,
TransactionBuilder transactionBuilder) {
opState.getDeviceInfo().updateDeviceOperData(LogicalSwitches.class, lsIid, new UUID("ls0"), "ls0");
opState.getDeviceInfo().onOperDataAvailable();
+ //wait for sometime so that the onDependencyResolved is triggered
+ Thread.sleep(500);
assertEquals(0, latch.getCount());
}