2 * Copyright (c) 2014, 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.applications.frm.impl;
10 import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.getActiveBundle;
11 import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.getNodeIdValueFromNodeIdentifier;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.common.api.CommitInfo;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.StaleGroup;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.StaleGroupBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.StaleGroupKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.common.Uint32;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * GroupForwarder It implements
50 * {@link org.opendaylight.mdsal.binding.api.DataTreeChangeListener}
51 * for WildCardedPath to {@link Group} and ForwardingRulesCommiter interface for
52 * methods: add, update and remove {@link Group} processing for
53 * {@link org.opendaylight.mdsal.binding.api.DataTreeModification}.
55 public class GroupForwarder extends AbstractListeningCommiter<Group> {
56 private static final Logger LOG = LoggerFactory.getLogger(GroupForwarder.class);
58 public GroupForwarder(final ForwardingRulesManager manager, final DataBroker db,
59 final ListenerRegistrationHelper registrationHelper) {
60 super(manager, db, registrationHelper);
64 protected InstanceIdentifier<Group> getWildCardPath() {
65 return InstanceIdentifier.create(Nodes.class)
67 .augmentation(FlowCapableNode.class)
72 public void remove(final InstanceIdentifier<Group> identifier, final Group removeDataObj,
73 final InstanceIdentifier<FlowCapableNode> nodeIdent) {
74 BundleId bundleId = getActiveBundle(nodeIdent, provider);
75 if (bundleId != null) {
76 provider.getBundleGroupListener().remove(identifier, removeDataObj, nodeIdent, bundleId);
78 final String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
79 nodeConfigurator.enqueueJob(nodeId, () -> {
80 final var removeGroup = new RemoveGroupInputBuilder(removeDataObj)
81 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
82 .setGroupRef(new GroupRef(identifier))
83 .setTransactionUri(new Uri(provider.getNewTransactionId()))
86 final var resultFuture = provider.getSalGroupService() .removeGroup(removeGroup);
87 Futures.addCallback(resultFuture,
88 new RemoveGroupCallBack(removeDataObj.getGroupId().getValue(), nodeId),
89 MoreExecutors.directExecutor());
90 return LoggingFutures.addErrorLogging(resultFuture, LOG, "removeGroup");
95 // TODO: Pull this into ForwardingRulesCommiter and override it here
97 public ListenableFuture<RpcResult<RemoveGroupOutput>> removeWithResult(final InstanceIdentifier<Group> identifier,
98 final Group removeDataObj, final InstanceIdentifier<FlowCapableNode> nodeIdent) {
99 return provider.getSalGroupService().removeGroup(new RemoveGroupInputBuilder(removeDataObj)
100 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
101 .setGroupRef(new GroupRef(identifier))
102 .setTransactionUri(new Uri(provider.getNewTransactionId()))
107 public void update(final InstanceIdentifier<Group> identifier, final Group original, final Group update,
108 final InstanceIdentifier<FlowCapableNode> nodeIdent) {
109 BundleId bundleId = getActiveBundle(nodeIdent, provider);
110 if (bundleId != null) {
111 provider.getBundleGroupListener().update(identifier, original, update, nodeIdent, bundleId);
113 final String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
114 nodeConfigurator.enqueueJob(nodeId, () -> {
115 final var updateGroupInput = new UpdateGroupInputBuilder()
116 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
117 .setGroupRef(new GroupRef(identifier))
118 .setTransactionUri(new Uri(provider.getNewTransactionId()))
119 .setUpdatedGroup(new UpdatedGroupBuilder(update).build())
120 .setOriginalGroup(new OriginalGroupBuilder(original).build())
122 final var resultFuture = LoggingFutures.addErrorLogging(
123 provider.getSalGroupService().updateGroup(updateGroupInput), LOG, "updateGroup");
124 Futures.addCallback(resultFuture,
125 new UpdateGroupCallBack(updateGroupInput.getOriginalGroup().getGroupId().getValue(), nodeId),
126 MoreExecutors.directExecutor());
133 public ListenableFuture<? extends RpcResult<?>> add(final InstanceIdentifier<Group> identifier,
134 final Group addDataObj, final InstanceIdentifier<FlowCapableNode> nodeIdent) {
135 final var bundleId = getActiveBundle(nodeIdent, provider);
136 if (bundleId != null) {
137 return provider.getBundleGroupListener().add(identifier, addDataObj, nodeIdent, bundleId);
140 final String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
141 return nodeConfigurator.enqueueJob(nodeId, () -> {
142 final var addGroupInput = new AddGroupInputBuilder(addDataObj)
143 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
144 .setGroupRef(new GroupRef(identifier))
145 .setTransactionUri(new Uri(provider.getNewTransactionId()))
147 final var resultFuture = provider.getSalGroupService().addGroup(addGroupInput);
148 Futures.addCallback(resultFuture,
149 new AddGroupCallBack(addGroupInput.getGroupId().getValue(), nodeId),
150 MoreExecutors.directExecutor());
156 public void createStaleMarkEntity(final InstanceIdentifier<Group> identifier, final Group del,
157 final InstanceIdentifier<FlowCapableNode> nodeIdent) {
158 LOG.debug("Creating Stale-Mark entry for the switch {} for Group {} ", nodeIdent, del);
159 final var staleGroup = new StaleGroupBuilder(del).setGroupId(del.getGroupId()).build();
160 final var writeTransaction = dataBroker.newWriteOnlyTransaction();
161 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, getStaleGroupInstanceIdentifier(staleGroup, nodeIdent),
163 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
165 public void onSuccess(final CommitInfo result) {
166 LOG.debug("Stale Group creation success");
170 public void onFailure(final Throwable throwable) {
171 LOG.error("Stale Group creation failed", throwable);
173 }, MoreExecutors.directExecutor());
176 private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.group
177 .types.rev131018.groups.StaleGroup> getStaleGroupInstanceIdentifier(
178 final StaleGroup staleGroup, final InstanceIdentifier<FlowCapableNode> nodeIdent) {
179 return nodeIdent.child(StaleGroup.class, new StaleGroupKey(new GroupId(staleGroup.getGroupId())));
182 private final class AddGroupCallBack implements FutureCallback<RpcResult<AddGroupOutput>> {
183 private final Uint32 groupId;
184 private final String nodeId;
186 private AddGroupCallBack(final Uint32 groupId, final String nodeId) {
187 this.groupId = groupId;
188 this.nodeId = nodeId;
192 public void onSuccess(final RpcResult<AddGroupOutput> result) {
193 if (result.isSuccessful()) {
194 provider.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
195 LOG.debug("Group add with id {} finished without error for node {}", groupId, nodeId);
197 LOG.debug("Group add with id {} failed for node {} with error {}", groupId, nodeId,
203 public void onFailure(final Throwable throwable) {
204 LOG.error("Service call for adding group {} failed for node with error {}", groupId, nodeId, throwable);
208 private final class UpdateGroupCallBack implements FutureCallback<RpcResult<UpdateGroupOutput>> {
209 private final Uint32 groupId;
210 private final String nodeId;
212 private UpdateGroupCallBack(final Uint32 groupId, final String nodeId) {
213 this.groupId = groupId;
214 this.nodeId = nodeId;
218 public void onSuccess(final RpcResult<UpdateGroupOutput> result) {
219 if (result.isSuccessful()) {
220 provider.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
221 LOG.debug("Group update with id {} finished without error for node {}", groupId, nodeId);
223 LOG.debug("Group update with id {} failed for node {} with error {}", groupId, nodeId,
224 result.getErrors().toString());
229 public void onFailure(final Throwable throwable) {
230 LOG.error("Service call for updating group {} failed for node {} with", groupId, nodeId,
235 private final class RemoveGroupCallBack implements FutureCallback<RpcResult<RemoveGroupOutput>> {
236 private final Uint32 groupId;
237 private final String nodeId;
239 private RemoveGroupCallBack(final Uint32 groupId, final String nodeId) {
240 this.groupId = groupId;
241 this.nodeId = nodeId;
245 public void onSuccess(final RpcResult<RemoveGroupOutput> result) {
246 if (result.isSuccessful()) {
247 LOG.debug("Group remove with id {} finished without error for node {}", groupId, nodeId);
248 provider.getDevicesGroupRegistry().removeGroup(nodeId, groupId);
250 LOG.debug("Group remove with id {} failed for node {} with error {}", groupId, nodeId,
251 result.getErrors().toString());
256 public void onFailure(final Throwable throwable) {
257 LOG.error("Service call for removing group {} failed for node with error {}", groupId, nodeId, throwable);