use of org.opendaylight.yangtools.yang.binding.InstanceIdentifier in project openflowplugin by opendaylight.
the class FlowNodeReconciliationImpl method reconciliationPreProcess.
private void reconciliationPreProcess(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
List<InstanceIdentifier<StaleFlow>> staleFlowsToBeBulkDeleted = Lists.newArrayList();
List<InstanceIdentifier<StaleGroup>> staleGroupsToBeBulkDeleted = Lists.newArrayList();
List<InstanceIdentifier<StaleMeter>> staleMetersToBeBulkDeleted = Lists.newArrayList();
ReadOnlyTransaction trans = provider.getReadTranaction();
Optional<FlowCapableNode> flowNode = Optional.absent();
try {
flowNode = trans.read(LogicalDatastoreType.CONFIGURATION, nodeIdent).get();
} catch (ExecutionException | InterruptedException e) {
LOG.warn("Reconciliation Pre-Processing Fail with read Config/DS for Node {} !", nodeIdent, e);
}
if (flowNode.isPresent()) {
LOG.debug("Proceeding with deletion of stale-marked Flows on switch {} using Openflow interface", nodeIdent.toString());
/* Stale-Flows - Stale-marked Flows have to be removed first for safety */
List<Table> tables = flowNode.get().getTable() != null ? flowNode.get().getTable() : Collections.<Table>emptyList();
for (Table table : tables) {
final KeyedInstanceIdentifier<Table, TableKey> tableIdent = nodeIdent.child(Table.class, table.getKey());
List<StaleFlow> staleFlows = table.getStaleFlow() != null ? table.getStaleFlow() : Collections.<StaleFlow>emptyList();
for (StaleFlow staleFlow : staleFlows) {
FlowBuilder flowBuilder = new FlowBuilder(staleFlow);
Flow toBeDeletedFlow = flowBuilder.setId(staleFlow.getId()).build();
final KeyedInstanceIdentifier<Flow, FlowKey> flowIdent = tableIdent.child(Flow.class, toBeDeletedFlow.getKey());
this.provider.getFlowCommiter().remove(flowIdent, toBeDeletedFlow, nodeIdent);
staleFlowsToBeBulkDeleted.add(getStaleFlowInstanceIdentifier(staleFlow, nodeIdent));
}
}
LOG.debug("Proceeding with deletion of stale-marked Groups for switch {} using Openflow interface", nodeIdent.toString());
// TODO: Should we collate the futures of RPC-calls to be sure that groups are
// Flows are fully deleted
// before attempting to delete groups - just in case there are references
/* Stale-marked Groups - Can be deleted after flows */
List<StaleGroup> staleGroups = flowNode.get().getStaleGroup() != null ? flowNode.get().getStaleGroup() : Collections.<StaleGroup>emptyList();
for (StaleGroup staleGroup : staleGroups) {
GroupBuilder groupBuilder = new GroupBuilder(staleGroup);
Group toBeDeletedGroup = groupBuilder.setGroupId(staleGroup.getGroupId()).build();
final KeyedInstanceIdentifier<Group, GroupKey> groupIdent = nodeIdent.child(Group.class, toBeDeletedGroup.getKey());
this.provider.getGroupCommiter().remove(groupIdent, toBeDeletedGroup, nodeIdent);
staleGroupsToBeBulkDeleted.add(getStaleGroupInstanceIdentifier(staleGroup, nodeIdent));
}
LOG.debug("Proceeding with deletion of stale-marked Meters for switch {} using Openflow interface", nodeIdent.toString());
/* Stale-marked Meters - can be deleted anytime - so least priority */
List<StaleMeter> staleMeters = flowNode.get().getStaleMeter() != null ? flowNode.get().getStaleMeter() : Collections.<StaleMeter>emptyList();
for (StaleMeter staleMeter : staleMeters) {
MeterBuilder meterBuilder = new MeterBuilder(staleMeter);
Meter toBeDeletedMeter = meterBuilder.setMeterId(staleMeter.getMeterId()).build();
final KeyedInstanceIdentifier<Meter, MeterKey> meterIdent = nodeIdent.child(Meter.class, toBeDeletedMeter.getKey());
this.provider.getMeterCommiter().remove(meterIdent, toBeDeletedMeter, nodeIdent);
staleMetersToBeBulkDeleted.add(getStaleMeterInstanceIdentifier(staleMeter, nodeIdent));
}
}
/* clean transaction */
trans.close();
LOG.debug("Deleting all stale-marked flows/groups/meters of for switch {} in Configuration DS", nodeIdent.toString());
// Now, do the bulk deletions
deleteDSStaleFlows(staleFlowsToBeBulkDeleted);
deleteDSStaleGroups(staleGroupsToBeBulkDeleted);
deleteDSStaleMeters(staleMetersToBeBulkDeleted);
}
use of org.opendaylight.yangtools.yang.binding.InstanceIdentifier in project openflowplugin by opendaylight.
the class SyncPlanPushStrategyIncrementalImpl method executeSyncStrategy.
@Override
public ListenableFuture<RpcResult<Void>> executeSyncStrategy(ListenableFuture<RpcResult<Void>> resultVehicle, final SynchronizationDiffInput diffInput, final SyncCrudCounters counters) {
final InstanceIdentifier<FlowCapableNode> nodeIdent = diffInput.getNodeIdent();
final NodeId nodeId = PathUtil.digNodeId(nodeIdent);
/* Tables - have to be pushed before groups */
// TODO enable table-update when ready
// resultVehicle = updateTableFeatures(nodeIdent, configTree);
resultVehicle = Futures.transformAsync(resultVehicle, input -> {
if (!input.isSuccessful()) {
// TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
// final ListenableFuture<RpcResult<Void>> singleVoidUpdateResult = Futures.transform(
// Futures.asList Arrays.asList(input, output),
// ReconcileUtil.<UpdateFlowOutput>createRpcResultCondenser("TODO"));
}
return addMissingGroups(nodeId, nodeIdent, diffInput.getGroupsToAddOrUpdate(), counters);
}, MoreExecutors.directExecutor());
Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "addMissingGroups"), MoreExecutors.directExecutor());
resultVehicle = Futures.transformAsync(resultVehicle, input -> {
if (!input.isSuccessful()) {
// TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
}
return addMissingMeters(nodeId, nodeIdent, diffInput.getMetersToAddOrUpdate(), counters);
}, MoreExecutors.directExecutor());
Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "addMissingMeters"), MoreExecutors.directExecutor());
resultVehicle = Futures.transformAsync(resultVehicle, input -> {
if (!input.isSuccessful()) {
// TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
}
return addMissingFlows(nodeId, nodeIdent, diffInput.getFlowsToAddOrUpdate(), counters);
}, MoreExecutors.directExecutor());
Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "addMissingFlows"), MoreExecutors.directExecutor());
resultVehicle = Futures.transformAsync(resultVehicle, input -> {
if (!input.isSuccessful()) {
// TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
}
return removeRedundantFlows(nodeId, nodeIdent, diffInput.getFlowsToRemove(), counters);
}, MoreExecutors.directExecutor());
Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "removeRedundantFlows"), MoreExecutors.directExecutor());
resultVehicle = Futures.transformAsync(resultVehicle, input -> {
if (!input.isSuccessful()) {
// TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
}
return removeRedundantMeters(nodeId, nodeIdent, diffInput.getMetersToRemove(), counters);
}, MoreExecutors.directExecutor());
Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "removeRedundantMeters"), MoreExecutors.directExecutor());
resultVehicle = Futures.transformAsync(resultVehicle, input -> {
if (!input.isSuccessful()) {
// TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
}
return removeRedundantGroups(nodeId, nodeIdent, diffInput.getGroupsToRemove(), counters);
}, MoreExecutors.directExecutor());
Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "removeRedundantGroups"), MoreExecutors.directExecutor());
return resultVehicle;
}
use of org.opendaylight.yangtools.yang.binding.InstanceIdentifier in project openflowplugin by opendaylight.
the class SyncPlanPushStrategyIncrementalImpl method addMissingGroups.
ListenableFuture<RpcResult<Void>> addMissingGroups(final NodeId nodeId, final InstanceIdentifier<FlowCapableNode> nodeIdent, final List<ItemSyncBox<Group>> groupsAddPlan, final SyncCrudCounters counters) {
if (groupsAddPlan.isEmpty()) {
LOG.trace("no groups configured for node: {} -> SKIPPING", nodeId.getValue());
return RpcResultBuilder.<Void>success().buildFuture();
}
ListenableFuture<RpcResult<Void>> chainedResult;
try {
if (!groupsAddPlan.isEmpty()) {
final CrudCounts groupCrudCounts = counters.getGroupCrudCounts();
groupCrudCounts.setAdded(ReconcileUtil.countTotalPushed(groupsAddPlan));
groupCrudCounts.setUpdated(ReconcileUtil.countTotalUpdated(groupsAddPlan));
if (LOG.isDebugEnabled()) {
LOG.debug("adding groups: planSteps={}, toAddTotal={}, toUpdateTotal={}", groupsAddPlan.size(), groupCrudCounts.getAdded(), groupCrudCounts.getUpdated());
}
chainedResult = flushAddGroupPortionAndBarrier(nodeIdent, groupsAddPlan.get(0));
for (final ItemSyncBox<Group> groupsPortion : Iterables.skip(groupsAddPlan, 1)) {
chainedResult = Futures.transformAsync(chainedResult, input -> {
final ListenableFuture<RpcResult<Void>> result;
if (input.isSuccessful()) {
result = flushAddGroupPortionAndBarrier(nodeIdent, groupsPortion);
} else {
// pass through original unsuccessful rpcResult
result = Futures.immediateFuture(input);
}
return result;
}, MoreExecutors.directExecutor());
}
} else {
chainedResult = RpcResultBuilder.<Void>success().buildFuture();
}
} catch (IllegalStateException e) {
chainedResult = RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "failed to add missing groups", e).buildFuture();
}
return chainedResult;
}
use of org.opendaylight.yangtools.yang.binding.InstanceIdentifier in project openflowplugin by opendaylight.
the class DeviceFlowRegistryImpl method fillFromDatastore.
private CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> fillFromDatastore(final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<FlowCapableNode> path) {
// Create new read-only transaction
final ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
// Bail out early if transaction is null
if (transaction == null) {
return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read transaction is null"));
}
// Prepare read operation from datastore for path
final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> future = transaction.read(logicalDatastoreType, path);
// Bail out early if future is null
if (future == null) {
return Futures.immediateFailedCheckedFuture(new ReadFailedException("Future from read transaction is null"));
}
Futures.addCallback(future, new FutureCallback<Optional<FlowCapableNode>>() {
@Override
public void onSuccess(@Nonnull Optional<FlowCapableNode> result) {
result.asSet().stream().filter(Objects::nonNull).filter(flowCapableNode -> Objects.nonNull(flowCapableNode.getTable())).flatMap(flowCapableNode -> flowCapableNode.getTable().stream()).filter(Objects::nonNull).filter(table -> Objects.nonNull(table.getFlow())).flatMap(table -> table.getFlow().stream()).filter(Objects::nonNull).filter(flow -> Objects.nonNull(flow.getId())).forEach(flowConsumer);
// After we are done with reading from datastore, close the transaction
transaction.close();
}
@Override
public void onFailure(Throwable throwable) {
// Even when read operation failed, close the transaction
transaction.close();
}
}, MoreExecutors.directExecutor());
return future;
}
use of org.opendaylight.yangtools.yang.binding.InstanceIdentifier in project openflowplugin by opendaylight.
the class TerminationPointChangeListenerImplTest method testOnNodeConnectorRemoved.
@SuppressWarnings("rawtypes")
@Test
public void testOnNodeConnectorRemoved() {
NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
final InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
Node topoNode = new NodeBuilder().setKey(topoNodeKey).build();
org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey = newInvNodeConnKey(terminationPointKey.getTpId().getValue());
final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")), newLink("link2", newSourceTp("source"), newDestTp("tp1")), newLink("link3", newSourceTp("source2"), newDestTp("dest2")));
final Topology topology = new TopologyBuilder().setLink(linkList).build();
final InstanceIdentifier[] expDeletedIIDs = { topologyIID.child(Link.class, linkList.get(0).getKey()), topologyIID.child(Link.class, linkList.get(1).getKey()), topologyIID.child(Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1"))) };
final SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
readFuture.set(Optional.of(topology));
ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
doReturn(Futures.makeChecked(readFuture, ReadFailedException.MAPPER)).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topologyIID);
SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
readFutureNode.set(Optional.of(topoNode));
doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
final CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
int expDeleteCalls = expDeletedIIDs.length;
CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
ArgumentCaptor<InstanceIdentifier> deletedLinkIDs = ArgumentCaptor.forClass(InstanceIdentifier.class);
setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
waitForSubmit(submitLatch1);
setReadFutureAsync(topology, readFuture);
waitForDeletes(expDeleteCalls, deleteLatch);
assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
verifyMockTx(mockTx1);
}
Aggregations