Merge "Add NodeConfiguratorImpl enqueue trace"
[openflowplugin.git] / applications / forwardingrules-manager / src / main / java / org / opendaylight / openflowplugin / applications / frm / impl / BundleGroupForwarder.java
1 /*
2  * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.applications.frm.impl;
10
11 import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.getNodeIdFromNodeIdentifier;
12 import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.isGroupExistsOnDevice;
13
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.JdkFutures;
22 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
23 import org.opendaylight.openflowplugin.applications.frm.NodeConfigurator;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.BundleInnerMessage;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleRemoveGroupCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleUpdateGroupCaseBuilder;
39 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;
40 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;
41 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;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
46 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 public class BundleGroupForwarder {
51
52     private static final Logger LOG = LoggerFactory.getLogger(BundleGroupForwarder.class);
53     private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
54     private final ForwardingRulesManager forwardingRulesManager;
55     private final NodeConfigurator nodeConfigurator;
56
57     public BundleGroupForwarder(final ForwardingRulesManager forwardingRulesManager) {
58         this.forwardingRulesManager = Preconditions.checkNotNull(forwardingRulesManager,
59                 "ForwardingRulesManager can not be null!");
60         this.nodeConfigurator = Preconditions.checkNotNull(forwardingRulesManager.getNodeConfigurator(),
61                 "NodeConfigurator can not be null!");
62     }
63
64     public void remove(final InstanceIdentifier<Group> identifier, final Group group,
65             final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
66         final NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
67         nodeConfigurator.enqueueJob(nodeId.getValue(), () -> {
68             final List<Message> messages = new ArrayList<>(1);
69             BundleInnerMessage bundleInnerMessage = new BundleRemoveGroupCaseBuilder()
70                     .setRemoveGroupCaseData(new RemoveGroupCaseDataBuilder(group).build()).build();
71             Message message = new MessageBuilder().setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
72                     .setBundleInnerMessage(bundleInnerMessage).build();
73             messages.add(message);
74             AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
75                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class))).setBundleId(bundleId)
76                     .setFlags(BUNDLE_FLAGS).setMessages(new MessagesBuilder().setMessage(messages).build()).build();
77             LOG.trace("Pushing group remove message {} to bundle {} for device {}", addBundleMessagesInput,
78                     bundleId.getValue(), nodeId.getValue());
79             final ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
80                     .getSalBundleService().addBundleMessages(addBundleMessagesInput);
81             Futures.addCallback(resultFuture, new BundleRemoveGroupCallBack(group.getGroupId().getValue(), nodeId),
82                     MoreExecutors.directExecutor());
83             JdkFutures.addErrorLogging(resultFuture, LOG, "removeBundleGroup");
84             return resultFuture;
85         });
86
87     }
88
89     public void update(final InstanceIdentifier<Group> identifier, final Group originalGroup, final Group updatedGroup,
90             final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
91         final NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
92         nodeConfigurator.enqueueJob(nodeId.getValue(), () -> {
93             final List<Message> messages = new ArrayList<>(1);
94             BundleInnerMessage bundleInnerMessage = new BundleUpdateGroupCaseBuilder()
95                     .setUpdateGroupCaseData(new UpdateGroupCaseDataBuilder(updatedGroup).build()).build();
96             Message message = new MessageBuilder().setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
97                     .setBundleInnerMessage(bundleInnerMessage).build();
98             messages.add(message);
99             AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
100                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class))).setBundleId(bundleId)
101                     .setFlags(BUNDLE_FLAGS).setMessages(new MessagesBuilder().setMessage(messages).build()).build();
102             LOG.trace("Pushing group update message {} to bundle {} for device {}", addBundleMessagesInput,
103                     bundleId.getValue(), nodeId.getValue());
104             final ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
105                     .getSalBundleService().addBundleMessages(addBundleMessagesInput);
106             Futures.addCallback(resultFuture, new BundleUpdateGroupCallBack(originalGroup.getGroupId().getValue(),
107                     nodeId), MoreExecutors.directExecutor());
108             JdkFutures.addErrorLogging(resultFuture, LOG, "updateBundleGroup");
109             return resultFuture;
110         });
111     }
112
113     public ListenableFuture<? extends RpcResult<?>> add(final InstanceIdentifier<Group> identifier, final Group group,
114             final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
115         final NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
116         final Long groupId = group.getGroupId().getValue();
117         return nodeConfigurator.enqueueJob(nodeId.getValue(), () -> {
118             if (isGroupExistsOnDevice(nodeIdent, groupId, forwardingRulesManager)) {
119                 LOG.debug("Group {} already exists in the device. Ignoring the add DTCN", groupId);
120                 return Futures.immediateFuture(RpcResultBuilder.<AddBundleMessagesOutput>success().build());
121             }
122             final List<Message> messages = new ArrayList<>(1);
123             BundleInnerMessage bundleInnerMessage = new BundleAddGroupCaseBuilder()
124                     .setAddGroupCaseData(new AddGroupCaseDataBuilder(group).build()).build();
125             Message message = new MessageBuilder().setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
126                     .setBundleInnerMessage(bundleInnerMessage).build();
127             messages.add(message);
128             AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
129                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class))).setBundleId(bundleId)
130                     .setFlags(BUNDLE_FLAGS).setMessages(new MessagesBuilder().setMessage(messages).build()).build();
131             LOG.trace("Pushing group add message {} to bundle {} for device {}", addBundleMessagesInput,
132                     bundleId.getValue(), nodeId.getValue());
133             ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
134                     .getSalBundleService().addBundleMessages(addBundleMessagesInput);
135             Futures.addCallback(resultFuture, new BundleAddGroupCallBack(groupId, nodeId),
136                     MoreExecutors.directExecutor());
137             return resultFuture;
138         });
139     }
140
141     private final class BundleAddGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
142         private final Long groupId;
143         private final NodeId nodeId;
144
145         private BundleAddGroupCallBack(final Long groupId, final NodeId nodeId) {
146             this.groupId = groupId;
147             this.nodeId = nodeId;
148         }
149
150         @Override
151         public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
152             if (result.isSuccessful()) {
153                 forwardingRulesManager.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
154                 LOG.debug("Group add with id {} finished without error for node {}", groupId, nodeId);
155             } else {
156                 LOG.debug("Group add with id {} failed for node {} with error {}", groupId, nodeId,
157                         result.getErrors().toString());
158             }
159         }
160
161         @Override
162         public void onFailure(Throwable throwable) {
163             LOG.error("Service call for adding group {} failed for node with error {}", groupId, nodeId, throwable);
164         }
165     }
166
167     private final class BundleUpdateGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
168         private final Long groupId;
169         private final NodeId nodeId;
170
171         private BundleUpdateGroupCallBack(final Long groupId, final NodeId nodeId) {
172             this.groupId = groupId;
173             this.nodeId = nodeId;
174         }
175
176         @Override
177         public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
178             if (result.isSuccessful()) {
179                 forwardingRulesManager.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
180                 LOG.debug("Group update with id {} finished without error for node {}", groupId, nodeId);
181             } else {
182                 LOG.debug("Group update with id {} failed for node {} with error {}", groupId, nodeId,
183                         result.getErrors().toString());
184             }
185         }
186
187         @Override
188         public void onFailure(Throwable throwable) {
189             LOG.error("Service call for updating group {} failed for node {}", groupId, nodeId, throwable);
190         }
191     }
192
193     private final class BundleRemoveGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
194         private final Long groupId;
195         private final NodeId nodeId;
196
197         private BundleRemoveGroupCallBack(final Long groupId, final NodeId nodeId) {
198             this.groupId = groupId;
199             this.nodeId = nodeId;
200         }
201
202         @Override
203         public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
204             if (result.isSuccessful()) {
205                 LOG.debug("Group remove with id {} finished without error for node {}", groupId, nodeId);
206                 forwardingRulesManager.getDevicesGroupRegistry().removeGroup(nodeId, groupId);
207             } else {
208                 LOG.debug("Group remove with id {} failed for node {} with error {}", groupId, nodeId,
209                         result.getErrors().toString());
210             }
211         }
212
213         @Override
214         public void onFailure(Throwable throwable) {
215             LOG.error("Service call for removing group {} failed for node with error {}", groupId, nodeId, throwable);
216         }
217     }
218
219 }