2 * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. 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
9 package org.opendaylight.openflowplugin.applications.frm.impl;
11 import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.getNodeIdValueFromNodeIdentifier;
12 import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.isGroupExistsOnDevice;
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import java.util.ArrayList;
20 import java.util.List;
21 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
22 import org.opendaylight.openflowplugin.applications.frm.BundleMessagesCommiter;
23 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
24 import org.opendaylight.openflowplugin.applications.frm.NodeConfigurator;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesOutput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.BundleInnerMessage;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleRemoveGroupCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleUpdateGroupCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.add.group._case.AddGroupCaseDataBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.remove.group._case.RemoveGroupCaseDataBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.update.group._case.UpdateGroupCaseDataBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
48 import org.opendaylight.yangtools.yang.common.Uint32;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class BundleGroupForwarder implements BundleMessagesCommiter<Group> {
54 private static final Logger LOG = LoggerFactory.getLogger(BundleGroupForwarder.class);
55 private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
56 private final ForwardingRulesManager forwardingRulesManager;
57 private final NodeConfigurator nodeConfigurator;
59 public BundleGroupForwarder(final ForwardingRulesManager forwardingRulesManager) {
60 this.forwardingRulesManager = Preconditions.checkNotNull(forwardingRulesManager,
61 "ForwardingRulesManager can not be null!");
62 this.nodeConfigurator = Preconditions.checkNotNull(forwardingRulesManager.getNodeConfigurator(),
63 "NodeConfigurator can not be null!");
67 public void remove(final InstanceIdentifier<Group> identifier, final Group group,
68 final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
69 final String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
70 nodeConfigurator.enqueueJob(nodeId, () -> {
71 final List<Message> messages = new ArrayList<>(1);
72 BundleInnerMessage bundleInnerMessage = new BundleRemoveGroupCaseBuilder()
73 .setRemoveGroupCaseData(new RemoveGroupCaseDataBuilder(group).build())
75 Message message = new MessageBuilder()
76 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
77 .setBundleInnerMessage(bundleInnerMessage)
79 messages.add(message);
80 AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
81 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
82 .setBundleId(bundleId)
83 .setFlags(BUNDLE_FLAGS)
84 .setMessages(new MessagesBuilder().setMessage(messages).build())
86 LOG.trace("Pushing group remove message {} to bundle {} for device {}", addBundleMessagesInput,
87 bundleId.getValue(), nodeId);
88 final ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
89 .getSalBundleService().addBundleMessages(addBundleMessagesInput);
90 Futures.addCallback(resultFuture,
91 new BundleRemoveGroupCallBack(group.getGroupId().getValue(), nodeId),
92 MoreExecutors.directExecutor());
93 LoggingFutures.addErrorLogging(resultFuture, LOG, "removeBundleGroup");
100 public void update(final InstanceIdentifier<Group> identifier,
101 final Group originalGroup,
102 final Group updatedGroup,
103 final InstanceIdentifier<FlowCapableNode> nodeIdent,
104 final BundleId bundleId) {
105 final String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
106 nodeConfigurator.enqueueJob(nodeId, () -> {
107 final List<Message> messages = new ArrayList<>(1);
108 BundleInnerMessage bundleInnerMessage = new BundleUpdateGroupCaseBuilder()
109 .setUpdateGroupCaseData(new UpdateGroupCaseDataBuilder(updatedGroup).build())
111 Message message = new MessageBuilder()
112 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
113 .setBundleInnerMessage(bundleInnerMessage)
115 messages.add(message);
116 AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
117 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
118 .setBundleId(bundleId)
119 .setFlags(BUNDLE_FLAGS)
120 .setMessages(new MessagesBuilder().setMessage(messages).build())
122 LOG.trace("Pushing group update message {} to bundle {} for device {}", addBundleMessagesInput,
123 bundleId.getValue(), nodeId);
124 final ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
125 .getSalBundleService()
126 .addBundleMessages(addBundleMessagesInput);
127 Futures.addCallback(resultFuture,
128 new BundleUpdateGroupCallBack(originalGroup.getGroupId().getValue(), nodeId),
129 MoreExecutors.directExecutor());
130 LoggingFutures.addErrorLogging(resultFuture, LOG, "updateBundleGroup");
136 public ListenableFuture<RpcResult<AddBundleMessagesOutput>> add(final InstanceIdentifier<Group> identifier,
138 final InstanceIdentifier<FlowCapableNode> nodeIdent,
139 final BundleId bundleId) {
140 final String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
141 final Uint32 groupId = group.getGroupId().getValue();
142 return nodeConfigurator.enqueueJob(nodeId, () -> {
143 if (isGroupExistsOnDevice(nodeIdent, groupId, forwardingRulesManager)) {
144 LOG.debug("Group {} already exists in the device. Ignoring the add DTCN", groupId);
145 return Futures.immediateFuture(RpcResultBuilder.<AddBundleMessagesOutput>success().build());
147 final List<Message> messages = new ArrayList<>(1);
148 BundleInnerMessage bundleInnerMessage = new BundleAddGroupCaseBuilder()
149 .setAddGroupCaseData(new AddGroupCaseDataBuilder(group).build())
151 Message message = new MessageBuilder()
152 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
153 .setBundleInnerMessage(bundleInnerMessage)
155 messages.add(message);
156 AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
157 .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
158 .setBundleId(bundleId)
159 .setFlags(BUNDLE_FLAGS)
160 .setMessages(new MessagesBuilder()
161 .setMessage(messages).build())
163 LOG.trace("Pushing group add message {} to bundle {} for device {}", addBundleMessagesInput,
164 bundleId.getValue(), nodeId);
165 ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
166 .getSalBundleService()
167 .addBundleMessages(addBundleMessagesInput);
168 Futures.addCallback(resultFuture,
169 new BundleAddGroupCallBack(groupId, nodeId),
170 MoreExecutors.directExecutor());
175 private final class BundleAddGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
176 private final Uint32 groupId;
177 private final String nodeId;
179 private BundleAddGroupCallBack(final Uint32 groupId, final String nodeId) {
180 this.groupId = groupId;
181 this.nodeId = nodeId;
185 public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
186 if (result.isSuccessful()) {
187 forwardingRulesManager.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
188 LOG.debug("Group add with id {} finished without error for node {}", groupId, nodeId);
190 LOG.error("Group add with id {} failed for node {} with error: {}", groupId, nodeId,
191 result.getErrors().toString());
196 public void onFailure(Throwable throwable) {
197 LOG.error("Service call for adding group {} failed for node {} with error ", groupId, nodeId, throwable);
201 private final class BundleUpdateGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
202 private final Uint32 groupId;
203 private final String nodeId;
205 private BundleUpdateGroupCallBack(final Uint32 groupId, final String nodeId) {
206 this.groupId = groupId;
207 this.nodeId = nodeId;
211 public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
212 if (result.isSuccessful()) {
213 forwardingRulesManager.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
214 LOG.debug("Group update with id {} finished without error for node {}", groupId, nodeId);
216 LOG.error("Group update with id {} failed for node {} with error: {}", groupId, nodeId,
217 result.getErrors().toString());
222 public void onFailure(Throwable throwable) {
223 LOG.error("Service call for updating group {} failed for node {}", groupId, nodeId, throwable);
227 private final class BundleRemoveGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
228 private final Uint32 groupId;
229 private final String nodeId;
231 private BundleRemoveGroupCallBack(final Uint32 groupId, final String nodeId) {
232 this.groupId = groupId;
233 this.nodeId = nodeId;
237 public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
238 if (result.isSuccessful()) {
239 LOG.debug("Group remove with id {} finished without error for node {}", groupId, nodeId);
240 forwardingRulesManager.getDevicesGroupRegistry().removeGroup(nodeId, groupId);
242 LOG.error("Group remove with id {} failed for node {} with error {}", groupId, nodeId,
243 result.getErrors().toString());
248 public void onFailure(Throwable throwable) {
249 LOG.error("Service call for removing group {} failed for node {} with error", groupId, nodeId, throwable);