Merge changes from topic "mdsal-4.0.3"
[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.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 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
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.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 public class BundleGroupForwarder implements BundleMessagesCommiter<Group> {
52
53     private static final Logger LOG = LoggerFactory.getLogger(BundleGroupForwarder.class);
54     private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
55     private final ForwardingRulesManager forwardingRulesManager;
56     private final NodeConfigurator nodeConfigurator;
57
58     public BundleGroupForwarder(final ForwardingRulesManager forwardingRulesManager) {
59         this.forwardingRulesManager = Preconditions.checkNotNull(forwardingRulesManager,
60                 "ForwardingRulesManager can not be null!");
61         this.nodeConfigurator = Preconditions.checkNotNull(forwardingRulesManager.getNodeConfigurator(),
62                 "NodeConfigurator can not be null!");
63     }
64
65     public void remove(final InstanceIdentifier<Group> identifier, final Group group,
66             final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
67         final NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
68         nodeConfigurator.enqueueJob(nodeId.getValue(), () -> {
69             final List<Message> messages = new ArrayList<>(1);
70             BundleInnerMessage bundleInnerMessage = new BundleRemoveGroupCaseBuilder()
71                     .setRemoveGroupCaseData(new RemoveGroupCaseDataBuilder(group).build()).build();
72             Message message = new MessageBuilder().setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
73                     .setBundleInnerMessage(bundleInnerMessage).build();
74             messages.add(message);
75             AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
76                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class))).setBundleId(bundleId)
77                     .setFlags(BUNDLE_FLAGS).setMessages(new MessagesBuilder().setMessage(messages).build()).build();
78             LOG.trace("Pushing group remove message {} to bundle {} for device {}", addBundleMessagesInput,
79                     bundleId.getValue(), nodeId.getValue());
80             final ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
81                     .getSalBundleService().addBundleMessages(addBundleMessagesInput);
82             Futures.addCallback(resultFuture, new BundleRemoveGroupCallBack(group.getGroupId().getValue(), nodeId),
83                     MoreExecutors.directExecutor());
84             LoggingFutures.addErrorLogging(resultFuture, LOG, "removeBundleGroup");
85             return resultFuture;
86         });
87
88     }
89
90     public void update(final InstanceIdentifier<Group> identifier, final Group originalGroup, final Group updatedGroup,
91             final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
92         final NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
93         nodeConfigurator.enqueueJob(nodeId.getValue(), () -> {
94             final List<Message> messages = new ArrayList<>(1);
95             BundleInnerMessage bundleInnerMessage = new BundleUpdateGroupCaseBuilder()
96                     .setUpdateGroupCaseData(new UpdateGroupCaseDataBuilder(updatedGroup).build()).build();
97             Message message = new MessageBuilder().setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
98                     .setBundleInnerMessage(bundleInnerMessage).build();
99             messages.add(message);
100             AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
101                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class))).setBundleId(bundleId)
102                     .setFlags(BUNDLE_FLAGS).setMessages(new MessagesBuilder().setMessage(messages).build()).build();
103             LOG.trace("Pushing group update message {} to bundle {} for device {}", addBundleMessagesInput,
104                     bundleId.getValue(), nodeId.getValue());
105             final ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
106                     .getSalBundleService().addBundleMessages(addBundleMessagesInput);
107             Futures.addCallback(resultFuture, new BundleUpdateGroupCallBack(originalGroup.getGroupId().getValue(),
108                     nodeId), MoreExecutors.directExecutor());
109             LoggingFutures.addErrorLogging(resultFuture, LOG, "updateBundleGroup");
110             return resultFuture;
111         });
112     }
113
114     @Override
115     public ListenableFuture<RpcResult<AddBundleMessagesOutput>> add(final InstanceIdentifier<Group> identifier,
116                     final Group group, final InstanceIdentifier<FlowCapableNode> nodeIdent, final BundleId bundleId) {
117         final NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
118         final Long groupId = group.getGroupId().getValue();
119         return nodeConfigurator.enqueueJob(nodeId.getValue(), () -> {
120             if (isGroupExistsOnDevice(nodeIdent, groupId, forwardingRulesManager)) {
121                 LOG.debug("Group {} already exists in the device. Ignoring the add DTCN", groupId);
122                 return Futures.immediateFuture(RpcResultBuilder.<AddBundleMessagesOutput>success().build());
123             }
124             final List<Message> messages = new ArrayList<>(1);
125             BundleInnerMessage bundleInnerMessage = new BundleAddGroupCaseBuilder()
126                     .setAddGroupCaseData(new AddGroupCaseDataBuilder(group).build()).build();
127             Message message = new MessageBuilder().setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)))
128                     .setBundleInnerMessage(bundleInnerMessage).build();
129             messages.add(message);
130             AddBundleMessagesInput addBundleMessagesInput = new AddBundleMessagesInputBuilder()
131                     .setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class))).setBundleId(bundleId)
132                     .setFlags(BUNDLE_FLAGS).setMessages(new MessagesBuilder().setMessage(messages).build()).build();
133             LOG.trace("Pushing group add message {} to bundle {} for device {}", addBundleMessagesInput,
134                     bundleId.getValue(), nodeId.getValue());
135             ListenableFuture<RpcResult<AddBundleMessagesOutput>> resultFuture = forwardingRulesManager
136                     .getSalBundleService().addBundleMessages(addBundleMessagesInput);
137             Futures.addCallback(resultFuture, new BundleAddGroupCallBack(groupId, nodeId),
138                     MoreExecutors.directExecutor());
139             return resultFuture;
140         });
141     }
142
143     private final class BundleAddGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
144         private final Long groupId;
145         private final NodeId nodeId;
146
147         private BundleAddGroupCallBack(final Long groupId, final NodeId nodeId) {
148             this.groupId = groupId;
149             this.nodeId = nodeId;
150         }
151
152         @Override
153         public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
154             if (result.isSuccessful()) {
155                 forwardingRulesManager.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
156                 LOG.debug("Group add with id {} finished without error for node {}", groupId, nodeId);
157             } else {
158                 LOG.error("Group add with id {} failed for node {} with error: {}", groupId, nodeId,
159                         result.getErrors().toString());
160             }
161         }
162
163         @Override
164         public void onFailure(Throwable throwable) {
165             LOG.error("Service call for adding group {} failed for node {} with error ", groupId, nodeId, throwable);
166         }
167     }
168
169     private final class BundleUpdateGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
170         private final Long groupId;
171         private final NodeId nodeId;
172
173         private BundleUpdateGroupCallBack(final Long groupId, final NodeId nodeId) {
174             this.groupId = groupId;
175             this.nodeId = nodeId;
176         }
177
178         @Override
179         public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
180             if (result.isSuccessful()) {
181                 forwardingRulesManager.getDevicesGroupRegistry().storeGroup(nodeId, groupId);
182                 LOG.debug("Group update with id {} finished without error for node {}", groupId, nodeId);
183             } else {
184                 LOG.error("Group update with id {} failed for node {} with error: {}", groupId, nodeId,
185                         result.getErrors().toString());
186             }
187         }
188
189         @Override
190         public void onFailure(Throwable throwable) {
191             LOG.error("Service call for updating group {} failed for node {}", groupId, nodeId, throwable);
192         }
193     }
194
195     private final class BundleRemoveGroupCallBack implements FutureCallback<RpcResult<AddBundleMessagesOutput>> {
196         private final Long groupId;
197         private final NodeId nodeId;
198
199         private BundleRemoveGroupCallBack(final Long groupId, final NodeId nodeId) {
200             this.groupId = groupId;
201             this.nodeId = nodeId;
202         }
203
204         @Override
205         public void onSuccess(RpcResult<AddBundleMessagesOutput> result) {
206             if (result.isSuccessful()) {
207                 LOG.debug("Group remove with id {} finished without error for node {}", groupId, nodeId);
208                 forwardingRulesManager.getDevicesGroupRegistry().removeGroup(nodeId, groupId);
209             } else {
210                 LOG.error("Group remove with id {} failed for node {} with error {}", groupId, nodeId,
211                         result.getErrors().toString());
212             }
213         }
214
215         @Override
216         public void onFailure(Throwable throwable) {
217             LOG.error("Service call for removing group {} failed for node {} with error", groupId, nodeId, throwable);
218         }
219     }
220
221 }