Merge "OPNFLWPLUG-1084 Device operational is not getting created if device reconcilia...
[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.getNodeIdValueFromNodeIdentifier;
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.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;
27
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;
51
52 public class BundleGroupForwarder implements BundleMessagesCommiter<Group> {
53
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;
58
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!");
64     }
65
66     @Override
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())
74                     .build();
75             Message message = new MessageBuilder()
76                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
77                     .setBundleInnerMessage(bundleInnerMessage)
78                     .build();
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())
85                     .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");
94             return resultFuture;
95         });
96
97     }
98
99     @Override
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())
110                     .build();
111             Message message = new MessageBuilder()
112                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
113                     .setBundleInnerMessage(bundleInnerMessage)
114                     .build();
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())
121                     .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");
131             return resultFuture;
132         });
133     }
134
135     @Override
136     public ListenableFuture<RpcResult<AddBundleMessagesOutput>> add(final InstanceIdentifier<Group> identifier,
137                                                                     final Group group,
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());
146             }
147             final List<Message> messages = new ArrayList<>(1);
148             BundleInnerMessage bundleInnerMessage = new BundleAddGroupCaseBuilder()
149                     .setAddGroupCaseData(new AddGroupCaseDataBuilder(group).build())
150                     .build();
151             Message message = new MessageBuilder()
152                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
153                     .setBundleInnerMessage(bundleInnerMessage)
154                     .build();
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())
162                     .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());
171             return resultFuture;
172         });
173     }
174
175     private final class BundleAddGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
176         private final Uint32 groupId;
177         private final String nodeId;
178
179         private BundleAddGroupCallBack(final Uint32 groupId, final String nodeId) {
180             this.groupId = groupId;
181             this.nodeId = nodeId;
182         }
183
184         @Override
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);
189             } else {
190                 LOG.error("Group add with id {} failed for node {} with error: {}", groupId, nodeId,
191                         result.getErrors().toString());
192             }
193         }
194
195         @Override
196         public void onFailure(Throwable throwable) {
197             LOG.error("Service call for adding group {} failed for node {} with error ", groupId, nodeId, throwable);
198         }
199     }
200
201     private final class BundleUpdateGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
202         private final Uint32 groupId;
203         private final String nodeId;
204
205         private BundleUpdateGroupCallBack(final Uint32 groupId, final String nodeId) {
206             this.groupId = groupId;
207             this.nodeId = nodeId;
208         }
209
210         @Override
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);
215             } else {
216                 LOG.error("Group update with id {} failed for node {} with error: {}", groupId, nodeId,
217                         result.getErrors().toString());
218             }
219         }
220
221         @Override
222         public void onFailure(Throwable throwable) {
223             LOG.error("Service call for updating group {} failed for node {}", groupId, nodeId, throwable);
224         }
225     }
226
227     private final class BundleRemoveGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
228         private final Uint32 groupId;
229         private final String nodeId;
230
231         private BundleRemoveGroupCallBack(final Uint32 groupId, final String nodeId) {
232             this.groupId = groupId;
233             this.nodeId = nodeId;
234         }
235
236         @Override
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);
241             } else {
242                 LOG.error("Group remove with id {} failed for node {} with error {}", groupId, nodeId,
243                         result.getErrors().toString());
244             }
245         }
246
247         @Override
248         public void onFailure(Throwable throwable) {
249             LOG.error("Service call for removing group {} failed for node {} with error", groupId, nodeId, throwable);
250         }
251     }
252 }